0

I decided to write RMI (from the book) took code from the book too. i created the Stub with rmic, and started rmiregistry but when i dedided to write java Start Server i got the problem, actually here is my problem i faced with: java -classpath D:\RMI AddServer Exception:java.rmi.ServerException: RemoteException occurred in server thread; n ested exception is: java.rmi.UnmarshalException: error unmarshalling arguments; nested excep tion is: java.lang.ClassNotFoundException: AddServerImpl_Stub PLease i need help, i lost lot of time because of this :(

AddServerIntf.java

package rmi.app;
import java.rmi.*;
 public interface AddServerIntf extends Remote {
  double add(double d1,double d2) throws RemoteException;}

AddServerImpl

package rmi.app;
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;
    }

}

AddServer

   package rmi.app;
    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);
    }

}

  }

AddClient

   package rmi.app;
   import java.rmi.Naming;
    public class AddClient {
public static void main(String[] args) {

    try{
        String addServerURL= "rmi://"+args[0]+ "/AddServer";
        AddServerIntf addServer =(AddServerIntf)Naming.lookup(addServerURL);
        System.out.println("The first number is:"+args[1]);
        double d1= Double.valueOf(args[1]).doubleValue();
        System.out.println("The second number is:"+args[2]);
        double d2= Double.valueOf(args[2]).doubleValue();
        System.out.println("the sum is:"+ addServer.add(d1,d2));

    }
    catch(Exception e){
        System.out.println("Exception : "+ e);
    }

}

     }

4 Answers4

2

I am writing a Java RMI application too and I went through a lot before being able to make it work. After a lot of research and try and error I got this "recipe":

  1. Don't install SecurityManager;
  2. Don't use policy files;
  3. Make sure the classes you're moving from one VM to another are in both client and server classpath (or in the same jar/war).
  4. If you're using hibernate to make database access, put the jars in the client too. Hibernate "changes" the original classes and the client will need this to deserialize it;
  5. If you're also using Spring on the server side you might include the spring-orm and spring-data-jpa jars in the client, if you experience ClassNotFoundException followed by JpaObjectRetrievalFailureException;
  6. I am not running anything outside the jars (no rmi services at all);
  7. I didn't create the stubs as I am using Java 6.

My server is purely doing this:

try {
        try {
            LocateRegistry.createRegistry(SERVER_PORT);
        } catch (RemoteException e) {
            LocateRegistry.getRegistry(SERVER_PORT);
            e.printStackTrace();
        }
        System.setProperty("java.rmi.server.hostname", SERVER_HOST);
        connectionRequestHandler = new ConnectionRequestHandlerImpl();
        dataRequestHandler = new DataRequestHandlerImpl();
        String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/";
        Naming.rebind(rmiUrl + "ConnectionRequestHandler", connectionRequestHandler);
        Naming.rebind(rmiUrl + "DataRequestHandler", dataRequestHandler);
    } catch (RemoteException e1) {
        e1.printStackTrace();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

Then on client I am doing:

String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/";
    try {
        connectionRequestHandler = (ConnectionRequestHandler)Naming.lookup(rmiUrl + "ConnectionRequestHandler");
        dataRequestHandler = (DataRequestHandler)Naming.lookup(rmiUrl + "DataRequestHandler");
    } catch (MalformedURLException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (RemoteException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (NotBoundException e) {
        throw new RmiServicesDownException(e.getMessage());
    } catch (Exception e ){
        e.printStackTrace();
        return;
    }

This is how it's working for me. Any other problems you may have are easy to solve compared to the first setup.

Paulo Pedroso
  • 3,555
  • 2
  • 29
  • 34
  • I would add to that list "don't use the codebase feature": at least not at first. It's a *deployment* option: don't let it mess up your initial development. If you plan to use it, just remember that it does mandate a SecurityManager and policy files, but you can figure those out later. – user207421 Mar 22 '13 at 22:55
1

Short answer: the registry needs to have the stubs on its classpath.

Long answer: find an rmi tutorial from within the last 10 years which doesn't use rmic, cause you haven't need to do all that for a long time.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • This is hard, I spent almost 2 weeks researching it and the material out there is very incomplete. :-) – Paulo Pedroso Mar 22 '13 at 17:58
  • @PauloPedroso - the top 2 hits for "java rmi tutorial" are both up to date and reasonably complete http://docs.oracle.com/javase/tutorial/rmi/index.html and http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html (neither uses rmic). – jtahlborn Mar 22 '13 at 18:26
  • @PauloPedroso - although i agree with your answer that you shouldn't use the SecurityManager and policy stuff, which just clutters the main tutorial. – jtahlborn Mar 22 '13 at 18:28
  • Yes, I went though this tutorial several times and it's hard to figure out what to do and don't do with so many controversial material out there. – Paulo Pedroso Mar 22 '13 at 18:39
  • guys but i took the example from book and i thought that it will go properly) – Olexander Haliy Mar 23 '13 at 11:18
1

Change the AddServerImpl constructor to call super(0). Then you don't even need to generate a stub, let alone deploy it. See the preamble to the Javadoc of UnicastRemoteObject.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

start rmiregistry from the server code directory. (or) Execute with -j option Please refer How do I set the classpath that rmiregistry uses? and javadoc reference [here]

Community
  • 1
  • 1
anavaras lamurep
  • 1,303
  • 2
  • 17
  • 33