0

I have rmi server and I have several network adapters on my computer.

In order not to get java.rmi.ConnectException: Connection refused to host: 127.0.1.1; I need to set the java.rmi.server.hostname property on my rmi server (see https://stackoverflow.com/a/15696021/5057736)

Does it mean that in one instance of JVM the rmi server at the same time can work only with one network interface without any OS settings?

Community
  • 1
  • 1
Pavel_K
  • 10,748
  • 13
  • 73
  • 186

2 Answers2

0

Setting java.rmi.server.hostname only affects what is written into the stub. It has no effect on listening. RMI always listens at 0.0.0.0 unless you use an RMIServerSocketFactory that doesn't.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • @JimJim2000 If you're going to have a lot more of these questions may I suggest you get a hold of my book *java.rmi: the Guide to Remote Method Invocation,* Pitt & McNiff, Addison Wesley 2001. No longer in print but plenty of s/h copies around. Everything you've asked so far is covered in there. – user207421 Jul 31 '16 at 05:54
  • Thank you for your suggestions, I will take a look. What about your answer. Let's suppose we have one instance of JVM and there are two RmiServers 192.168.1.0:2525 and 192.168.1.1:3636 on it. Then stubs only for one server will work because as I understand from your answer in ALL stubs will be written the same `java.rmi.server.hostname`? – Pavel_K Aug 01 '16 at 12:37
  • Some time passed, and I am back to this problem. Yes, what I wrote is correct. But it doesn't give the solution, only explain the problem. I've read many your posts on different sites and unfortunately I couldn't find that you suggested any solution to solve situation when there are several network interfaces and one instance JVM that create different RMI servers on different network interfaces. Can you say if you know solution to such problem? – Pavel_K Apr 01 '17 at 15:08
  • @Pavel_K What problem? I've answered here that it listens on 0.0.0.0. That eliminates any problem with any number of network interfaces. – user207421 Apr 25 '20 at 05:27
-1

After reading https://community.oracle.com/blogs/emcmanus/2006/12/22/multihomed-computers-and-rmi and this https://community.oracle.com/thread/1178328?start=0 I did the following solution - in all aplication exporting RMIRemoteObjects we put in one place. This solution allows RMI to work with different network interfaces at the same time in one instance of JVM. RmiRemoteManager is created for every socket address (network interface + port). Before exporting we need to define java.rmi.server.hostname. This solution works. Please, remember that it is workaround for RMI limitation.

class ClientSocketFactory implements RMIClientSocketFactory,Serializable{

    private InetAddress address;

    public ClientSocketFactory(InetAddress address)
    {
        this.address = address;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
        Socket socket =new Socket(address, port);
        return socket;
    }

    @Override
    public boolean equals(Object that)
    {
        return that != null && this.getClass() == that.getClass();
    }
}

class ServerSocketFactory implements RMIServerSocketFactory{

    private InetAddress address;

    public ServerSocketFactory(InetAddress address)
    {
        this.address = address;
    }

    @Override
    public ServerSocket createServerSocket(int port) throws IOException{  
        return new ServerSocket(port, 0, address);
    }

    @Override
    public boolean equals(Object that)
    {
        return that != null && this.getClass() == that.getClass();
    }
}

public class RmiRemoteManager {

    private Registry registry;

    private InetSocketAddress socketAddress;

    private ServerSocketFactory serverSocketFactory;

    private ClientSocketFactory clientSocketFactory;

    public RmiRemoteManager(InetSocketAddress socketAddress) {
        try {
            this.socketAddress = socketAddress;
            serverSocketFactory=new ServerSocketFactory(InetAddress.getByName(socketAddress.getHostName()));
            clientSocketFactory=new ClientSocketFactory(InetAddress.getByName(socketAddress.getHostName()));
            //the registry is exported via createRegistry.
            registry = LocateRegistry.createRegistry(this.socketAddress.getPort(),clientSocketFactory,serverSocketFactory);
        } catch (UnknownHostException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private synchronized static Remote export(Remote remoteObject,InetSocketAddress sa,ClientSocketFactory csf,ServerSocketFactory ssf){
        try {
            System.setProperty("java.rmi.server.hostname",sa.getHostName());
            return UnicastRemoteObject.exportObject(remoteObject,sa.getPort(),csf,ssf);
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void export(Remote remoteObject,String url){
        try {
            Remote stub=export(remoteObject,socketAddress,clientSocketFactory,serverSocketFactory);
            remoteObjects.add(remoteObject);
            if (url!=null){
                urlsByRemoteObjects.put(remoteObject, url);
                registry.rebind(url, stub);
            }
        } catch (RemoteException ex) {
            Logger.getLogger(RmiRemoteManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
Pavel_K
  • 10,748
  • 13
  • 73
  • 186
  • This is all completely unnecessary. There is no actual problem to solve. There is no such 'RMI limitation' as you are alleging. I am not wrong about this. – user207421 Apr 25 '20 at 05:28