Search code examples
javarmi

How to register remote object with RMI registry?


I'm trying to get these Java RMI Trails from the Oracle tutorials to work but I can't seem to. I keep getting the following error when trying to start the server:

java.security.AccessControlException: access denied ("java.net.SocketPermission" 
"127.0.0.1:1099" "connect,resolve")

The trace point to the invokation of registry.rebind(name, stub);

The project is a Server application to which one can send Tasks (a remote interface) and provides a Remote interface Compute, to preform this task. The Client side of the application provides an implementation of Task that calculates Pi.

When trying to follow this I've set up two projects 'ComputeEngine' and 'ComputeClient' as: Project structure

Where 'compute.jar' contains the interfaces Compute and Task.

I did do: 'start rmiregistry' before attempting to start the server (not sure I hade to before I started the client though).

Any hints as to what is going worng? Does it have anything to do with security policies, I'm not sure I understand what they do?

The code can be found in the link provided too but I'll post it here as well:

ComputeEngine.java

public class ComputeEngine implements Compute {

    public ComputeEngine() {
        super();
    }

    public <T> T executeTask(Task<T> t) {
        return t.execute();
    }

    public static void main(String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Compute";
            Compute engine = new ComputeEngine();
            Compute stub =
                (Compute) UnicastRemoteObject.exportObject(engine, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub); // <-- This is where the error points.
            System.out.println("ComputeEngine bound");
        } catch (Exception e) {
            System.err.println("ComputeEngine exception:");
            e.printStackTrace();
        }
    }
}

Compute.java

public interface Compute extends Remote {
    <T> T executeTask(Task<T> t) throws RemoteException;
}

Task.java

public interface Task<T> {
    T execute();
}

CopmutePi.java

public class ComputePi {
    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Compute";
            Registry registry = LocateRegistry.getRegistry(args[0]);
            Compute comp = (Compute) registry.lookup(name);
            Pi task = new Pi(Integer.parseInt(args[1]));
            BigDecimal pi = comp.executeTask(task);
            System.out.println(pi);
        } catch (Exception e) {
            System.err.println("ComputePi exception:");
            e.printStackTrace();
        }
    }    
}

Pi.java

public class Pi implements Task<BigDecimal>, Serializable {

    private static final long serialVersionUID = 227L;

    private static final BigDecimal FOUR =
        BigDecimal.valueOf(4);

    private static final int roundingMode = 
        BigDecimal.ROUND_HALF_EVEN;

    private final int digits;

    public Pi(int digits) {
        this.digits = digits;
    }

    public BigDecimal execute() {
        return computePi(digits);
    }

    public static BigDecimal computePi(int digits) {
        // computing Pi...
    }       
}

Solution

  • Get rid of the security manager and the codebase feature and try again. You only need the security manager if you use the codebase feature, and you only need the codebase feature if you're going to use it to deploy your application with. It is optional and generally not used, at least at tutorial stage.