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);
    }

}

     }
2
  • Which version of java are you using? Commented Mar 22, 2013 at 17:48
  • Take a look at my answer, you were probably putting your code in the question when I was writing it. You're probably too close. Commented Mar 22, 2013 at 17:56

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
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.

5 Comments

This is hard, I spent almost 2 weeks researching it and the material out there is very incomplete. :-)
@PauloPedroso - the top 2 hits for "java rmi tutorial" are both up to date and reasonably complete docs.oracle.com/javase/tutorial/rmi/index.html and docs.oracle.com/javase/6/docs/technotes/guides/rmi/hello/… (neither uses rmic).
@PauloPedroso - although i agree with your answer that you shouldn't use the SecurityManager and policy stuff, which just clutters the main tutorial.
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.
guys but i took the example from book and i thought that it will go properly)
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.

Comments

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]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.