0

I have two computers. On one of them, is running an RMI Registry - which was created from this code alone:

package main;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;

public class TheRegistry{

    public static void main(String[] args) {
        try {
            Registry reg = LocateRegistry.createRegistry(2020);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{
            System.out.println("Registry Created");
            Scanner input = new Scanner(System.in);
            input.nextInt();
            System.exit(0);
        }
    }
}

The other computer has a server that is trying to register an Object on this registry, however, it gets an exception. Here is the code for the server:

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.*;

public class TextScramblerServer implements TextScramblerInterface 
{
    private static Remote obj; 
    // main method to export
    @Override //Return input text as-is.
    public String testInputText(String inputText) {

        return "Your input text is: " + inputText;
    }

    @Override //Return the string reversed.
    public String reverse(String inputText) {
        String reversedInput = "";
        for(int i=0; i<inputText.length();i++)
        {
            reversedInput=reversedInput+inputText.charAt((inputText.length()-1)-i);
        }
        return "Result: "+reversedInput;
    }

    @Override //Return the string scrambled.
    public String scramble(String inputText) {
        String scrambledInput="";

        for(int i=0; i<inputText.length();i++)
        {
            if(i%2==0)
            {
                scrambledInput=scrambledInput+inputText.charAt(i);
            }
            else
            {
                scrambledInput=inputText.charAt(i)+scrambledInput;
            }
        }
        return "Result: "+scrambledInput;
    }

    public void exportServer() throws Exception {
        System.setSecurityManager(new RMISecurityManager());
        obj = UnicastRemoteObject.exportObject(this, 2022);
        Registry registry = LocateRegistry.getRegistry("132.205.94.50", 2020);
        registry.bind("test", obj);
    }

    public static void main(String[] args) {
        try {
            (new TextScramblerServer()).exportServer();
            System.out.println("Server is up and running");
        }
        catch(Exception e){
            e.printStackTrace();
            try {
                UnicastRemoteObject.unexportObject(obj, true); //close port
            } catch (NoSuchObjectException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }
}

I keep getting the error:

java.rmi.ConnectException: Connection refused to host: 132.205.94.50; nested exception is: 
    java.net.ConnectException: Connection refused: connect
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
    at sun.rmi.server.UnicastRef.newCall(Unknown Source)
    at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
    at TextScramblerServer.exportServer(TextScramblerServer.java:57)
    at TextScramblerServer.main(TextScramblerServer.java:62)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)
    ... 7 more
java.rmi.NoSuchObjectException: object not exported
    at sun.rmi.transport.ObjectTable.unexportObject(Unknown Source)
    at java.rmi.server.UnicastRemoteObject.unexportObject(Unknown Source)
    at TextScramblerServer.main(TextScramblerServer.java:68)

I can't figure out why this is happening. I think I've tried everything

CodyBugstein
  • 21,984
  • 61
  • 207
  • 363
  • does netstat show port 2020 as being in use? If yes perhaps `Registry reg` is being garbage collected? – rogerdpack Oct 01 '15 at 22:02
  • @rogerdpack yes it does (that machine is on ubuntu, so I used `lsof -i 2020`) – CodyBugstein Oct 01 '15 at 22:13
  • have you set the rigtht permissions in the server java policy file : ` // allows anyone to listen on dynamic ports permission java.net.SocketPermission "localhost:0", " listen, connect, read, write»; ` – fabien t Oct 01 '15 at 22:27
  • @fabient on the server? yes, there's a `security.policy` (configured in the VM) that gives all permissions. Hmmmm... does the registry need one too? – CodyBugstein Oct 01 '15 at 22:28
  • i see ConnectionExcepetion, and connection is refused so maybe it don't have the read access, and the write access for the find ? se this : https://books.google.ch/books?id=vhwlwVVsUlgC&pg=PA353&lpg=PA353&dq=rmi+write+read+access&source=bl&ots=Uz-3AgUM0q&sig=GUQTYcdzhalU08Mf6aAR5vyikR0&hl=fr&sa=X&ved=0CCUQ6AEwAWoVChMI1IGjsaqiyAIVyzsUCh0NkA2s#v=onepage&q=rmi%20write%20read%20access&f=false. It can be done by code to with Properties of the RMISecurityManager – fabien t Oct 01 '15 at 22:32
  • it's possible it's binding on the wrong "IP" somehow, try it with just both on same box and localhost... – rogerdpack Oct 01 '15 at 23:00
  • the security policy is in the JRE of App Server at $JAVA_HOME/jre/lib/security/security.policy – fabien t Oct 01 '15 at 23:14
  • Could it be that I should use `Naming.bind` instead of `Registry.bind`? – CodyBugstein Oct 02 '15 at 18:25
  • @Imray No it couldn't. – user207421 Oct 02 '15 at 19:44

2 Answers2

1

I ran your code and it worked for me after configuring the security policy.

Your ConnectionRefused exception means that the underlying TCP connection cannot be established. It's network issue, not an RMI issue.

Try running both the server and registry on the same host, and use localhost as the hostname. If it works, the problem is likely a firewall issue between the two hosts.

You can do a simple test of a TCP connection to the specific port using telnet. If the port isn't listening, telnet will give you a similar connection refused message. If the port is listening, you'll get something like this on the terminal:

Connected to localhost.
Escape character is '^]'.

Control-C to get out of the session.

The specific telnet output may vary based on your OS, but they are all about the same.

If it is a firewall issue, you'll have to open up the ports. How to do that depends on OS, but it's easy to find.

Community
  • 1
  • 1
Monz
  • 321
  • 2
  • 11
-1

Either your Registry has been garbage-collected, you got the IP address wrong, or it is a public IP address and you haven't configured port forwarding.

You need to store the Registry reference in a static object to overcome garbage collection, although what the point of that program is when rmiregistry.exe already exists escapes me completely.

You're barking up the wrong tree anyway. You can only bind to an RMI Registry that is running in the local host. There is therefore never any need to use a Registry hostname other than "localhost" when binding or unbinding.

The reason you got the NoSuchObjectException is that you are trying to unexport the stub, which is referred to by obj, which is the result of UnicastRemoteObject.exportObject(), which returns the stub. See the Javadoc. You need to save the result of new TextScramblerServer() and unexport that.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • `You can only bind to an RMI Registry that is running in the local host. ` Then what is the point of RMI? If everything has to be local there would be no point of distributed systems. – CodyBugstein Oct 02 '15 at 16:35
  • @Imray Everything doesn't have to be local. You can *lookup* a remote Registry. You just can't *bind* to a remote Registry. It's a security measure. – user207421 Oct 02 '15 at 19:42
  • Isn't the whole point of a registry so that a client doesn't have to know about all the different machines, but rather only has to know about the registry? – CodyBugstein Oct 02 '15 at 19:58
  • The whole point of the Registry is to solve the bootstrap problem. See my answer [here](http://stackoverflow.com/a/32914914/207421). – user207421 Oct 02 '15 at 20:00