Is this possible? (Assuming Java 6)
A contrived/simplistic example to illustrate my point is:
- I have a well-defined RMI interface that will never change (a single JAR file, no template parameters)
- an RMIRegistry running on host X;
- RMI Services which registry.rebind() to it (RMIRegistry on host X) from host Y; and
- RMI clients which perform RMI calls from host Z
If it is possible, how would I specify the property "java.rmi.server.codebase" on the RMI Service (process on host Y)?
If host A and B are the same machine, then this configuration works when the "java.rmi.server.codebase" is "file:///C:/rmiCodebase/myCommonInterface.jar"
If host A and B are on separate machines, then I get the following exception on the rebind (with the same "java.rmi.server.codebase" set on host Y):
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException:
If host A and B are on separate machines, and I make the interface JAR available through a web-server (where "java.rmi.server.codebase" is either "http://Y/rmiCodebase/myCommonInterface.jar" OR "开发者_运维技巧http://Z/rmiCodebase/myCommonInterface.jar"), then I get this slightly different error on the rebind:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Registry.Registry.rebind disallowed; origin /10.0.190.25 (host Y) is non-local host
I am a little confused - it seems very constraining if all RMI Services must run on the same physical host as the RMIRegistry (which is the only thing I have succeeded in getting working)
At the end of the day, I only want machine Z to be able to make an RMI call to a service running on machine Y. I am providing myCommonInterface.jar to the processes running on both machine Y and Z. I don't even want machine X to have to do anything with the common (remote) interface!
Whilst the following link is useful, it doesn't help me answer this question: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html
Is this possible?
No it is not possible. See the Javadoc for Registry.bind()/rebind()/unbind() and Naming.bind()/rebind()/unbind().
However you could use an LDAP service instead of the RMI Registry.
I only want machine Z to be able to make an RMI call to a service running on machine Y
So why the question? What's the problem with machine Z looking up a Registry at machine Y?
Not exactly a concrete answer, but hints at the restriction:
http://download.oracle.com/javase/6/docs/api/java/rmi/registry/Registry.html
A Registry implementation may choose to restrict access to some or all of its methods (for example, methods that mutate the registry's bindings may be restricted to calls originating from the local host). If a Registry method chooses to deny access for a given invocation, its implementation may throw AccessException, which (because it extends RemoteException) will be wrapped in a ServerException when caught by a remote client.
My use-case was very simple (basically, using RMI as a way to command a distributed system), but I was able to avoid using the registry all together.
Here's a work-around to that I ended up using for a Map-Reduce-miniframework.
Before:
In client:
remoteMaster = (Master) remoteRegistry.lookup("master");
// Add self to remote registry (BAD!)
Worker stub = (Worker) UnicastRemoteObject.exportObject(this, 15213);
remoteMaster.bind("workerName", stub);
After:
(In this workaround, we will save the RemoteObject manually, not using a registry)
In Master:
List<Worker> workers = new List<Worker>();
public void registerWorker(String name, Worker stub) throws RemoteException {
worker.add(stub);
}
Once you save the remote instance, you can pass it around and call it like any other object.
Note this approach is useful only if you're only using the registry as a temporary storage place (which I was), since you're just avoiding the "access restriction" by not adding it to the registry, and keeping it local.
Just documenting my (slightly hacky) solution, comments welcome.
精彩评论