Search code examples
javaserializationrmirpc

Java RMI - Returning a reference to another remote object on server from a remote method on server, to client


The issue is that with client-server communication using RMI - I don't know how I can return anything like an object (or a reference to an object) running on the server space, back to the client whose methods I can then call from that client. I need this because, the basic RMI examples merely pass data like strings or int etc. from server to client, not a fully serialized object running on server.

The only similar question I found was is it possible to pass by reference in RMI?

What I'm trying to do is this:

Server: Creates and exports a remote object (which implements a remote interface). The client calls a method of this remote object. This method in turn creates a new object of another class and returns a reference to it.

Client: Gets a stub from the Java RMI registry. Calls the stub as per the remote object specification and gets a handle to the other object, and then using this handle it invokes the methods of this object running in server space.

Is this even possible ? I may be missing a concept or two here as well.

Code:

//Hello.java
import java.rmi.Remote;
import java.rmi.RemoteException;


public interface Hello extends Remote {
    public target sayHello() throws RemoteException;
}






//Server.java   
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class Server implements Hello {
public target t;
public Server() {}

public target sayHello() {
    target t = new target(1,"target");
    return t;
}

public static void main(String args[]) {
Hello stub = null;
Registry registry = null;

try {
    Server obj = new Server();
    stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
    registry = LocateRegistry.getRegistry();
    registry.bind("Hello", stub);

    System.err.println("Server ready");
} catch (Exception e) {
    try{
    registry.unbind("Hello");
    registry.bind("Hello",stub);
        System.err.println("Server ready");
    }catch(Exception ee){
    System.err.println("Server exception: " + ee.toString());
        ee.printStackTrace();
    }
}
}
}




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

public class Client {

private Client() {}

public static void main(String[] args) {


String host = (args.length < 1) ? null : args[0];
try {

    Registry registry = LocateRegistry.getRegistry(host);
    Hello stub = (Hello) registry.lookup("Hello");
    target response = stub.sayHello(); //**Error string cannot be converted to type** target while compiling with javac
    System.out.println("response: " + response.getdesc());
} catch (Exception e) {
    System.err.println("Client exception: " + e.toString());
    e.printStackTrace();
}
}
}




//target.java
import java.io.*;

class target implements Serializable {
int data;
String desc;

target(int data, String desc) {
this.data = data;
this.desc = desc;
}

public int getdata() { return data; }
public String getdesc() { return desc; }

public void setdata(int data) { this.data = data; }
public void setdesc(String desc) { this.desc = desc; }
}

Solution

  • You just need to ensure that the object you return is an exported remote object, and that it's referred to in the remote interface that returns it by its own remote interface name, not its own name.