Java RMI simple Hello World program throwing RemoteException

10.5k views Asked by At

I have this strange problem. I'm trying to write a simple Hello World java program using RMI. Here are my files, all belonging to the same package:

Hello.java:

package com.something;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote{
    String hello() throws RemoteException;
}

Server.java

package com.something;
import com.something.Hello;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class Server implements Hello{

    @Override
    public String hello() throws RemoteException {
        return "hello world!!!!";
    }
public static void main (String args[]) throws RemoteException{

        //System.setProperty("java.rmi.server.hostname", "10.0.0.5");
                 if (System.getSecurityManager() == null) {
                        System.setSecurityManager(new SecurityManager());
                    }
                    try {
                        String name = "Hello";
                        Hello s = new Server();
                        Hello stub =
                            (Hello) UnicastRemoteObject.exportObject(s, 0);
                        Registry registry = LocateRegistry.getRegistry(8888);



                        registry.rebind(name, stub);
                        System.out.println("Hello bound");
                    } catch (Exception e) {
                        System.err.println("Hello exception:");
                        e.printStackTrace();
                    }
    }        

}       

Client.java:

package com.something; 


import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;



public class Client {
    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Hello";
            Registry registry = LocateRegistry.getRegistry("localhost"); 

            Hello h = (Hello) registry.lookup(name);
            System.out.println(h.hello());   
        } catch (Exception e) {
            System.err.println("My exception:");
            e.printStackTrace();
        }
    }    
}

Before runnig the code, in the terminal, I run:

rmiregistry 8888

I run the java code with the following flag: -Djava.security.policy=/Users/nataliazon/Documents/workspace/SiecioweRMI/src/server.policy

And here's my server.policy file:

grant {
   permission java.security.AllPermission;
};

When I run the Server program like that, the following exception is thrown:

Hello exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.something.Hello
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
    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:359)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at com.something.Server.main(Server.java:30)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.something.Hello
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException: com.something.Hello
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:709)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:653)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:590)
    at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    ... 12 more

And the Client program throws this:

My exception:
java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: 
    java.net.ConnectException: Connection refused
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at com.something.Client.main(Client.java:18)
Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at java.net.Socket.<init>(Socket.java:375)
    at java.net.Socket.<init>(Socket.java:189)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
    ... 5 more

How can this problem be solved?

1

There are 1 answers

0
user207421 On BEST ANSWER

java.lang.ClassNotFoundException: com.something.Hello

The Registry and the client don't have that class on their classpath.

In the case of the Registry the simplest solution is to start it in the server JVM. via LocateRegistry.createRegistry(): or else start it in such a way that the class is on its classpath; there are several ways to accomplish that.

java.rmi.ConnectException: Connection refused to host: localhost

That is caused by specifying "localhost" instead of the server host when calling Naming.lookup() or when calling LocateRegistry.getRegistry() prior to calling Registry.lookup(). The Registry isn't ubiquitous, it is located at the server host.

NB you don't need the SecurityManager unless you are using the RMI codebase feature or you have some other requirement for it.