RMI

Java Collections
Level 2 , Lesson 9
Available

"Hi! And one more happy topic: RMI. RMI stands for Remote Method Invocation. In other words, RMI is a mechanism that allows an object from one Java machine to call methods on objects from another Java machine, even if they are on different computers, in different countries, or on different sides of the globe."

RMI - 1

"Whoa! That sounds awesome."

"Yep. But I'll only try to give you an overview. With this, if you dig too deep, you can get confused by the nuances of how it works."

"But if you don’t go to extremes, then RMI is not only very simple, but it also greatly simplifies a programmer's life. For which, we pay it our deepest respects."

"So, we want one object in a Java program to call a method on an object that is in another Java program. Regardless of where these programs are running."

"Let's consider the simplest example: when both programs are running on the same computer. To allow programs to interact over the Internet, you need to configure the JVM's permissions, but we won't cover that today."

"In Java, you can remotely call only the methods of interfaces, not classes."

"So, we have two programs. How can they call each other's methods?"

"Let's consider the situation where one program contains an object, and a second program wants to call methods on that object. Let's call the first program the server, and the second — the client."

"First, I'll provide some sample code, and then we'll analyze it."

"So what will our program do?"

"Hmm. Well, for simplicity, the program will have one method that reverses a string that is passed to it."

"Simple enough."

"Good, then let's start:"

"First, we need an interface that will satisfy our requirements:"

Interface for communication between programs
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

"I created a Reverse interface and added a Remote marker interface to it, as well as a RemoteException. Unexpected errors could occur when the method is called. If any do, then this exception will be thrown."

"Now we need to write a server class that implements this interface:"

Class for the server
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

"I see. We reverse the string in this method."

"Yep."

"Now we need to make this object callable from another program. Here's how you do that:"

Object sharing
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

"I'll explain this line by line."

"In line 1, we store a unique name (which we made up) for our remote object (object that is remotely accessible) in the UNIC_BINDING_NAME variable. If the program makes several objects accessible, each must have its own unique name. The our object's unique name is 'server.reverse'."

"On line 6 we create a ReverseImpl object that will be accessible remotely. Its methods will be invoked."

"On line 9 we create a special object called a registry. We need to use it to register the objects that we share. The JVM will interact with them later. 2099 is a port (a unique number that another program can use to access our object registry)."

"In other words, to access an object, you need to know the object registry's unique number (port) and the object's unique name, and have the same interface as the one implemented by the remote object."

"I see. Something like: call by phone (need a number) and ask for Bill (the name of an object)?"

"Yes. Now, let's keep going."

"On line 11 , we create a stub. A stub is a special object that receives information about the remote call, unpacks it, deserializes the method arguments, and calls the required method. Then it serializes the result or exception, if there was one, and sends it all back to the caller."

"I see. Almost. You said that it 'deserializes the method arguments'. So, that means the remote methods' arguments must be serializable?"

"Yes. How else would you send them over the network? True, there are exceptions, i.e. objects that are passed by reference, but we won't talk about them today."

"We'll put it like this: you can't pass non-serializable objects, but if you really want to, then you can. But it's a pain, you know."

"OK."

"Then let's keep going."

"On line 13, we register our object's stub under a unique name in the registry."

"On line 16, we put the main thread to sleep. All remote calls are processed on separate threads. The important thing is that the program is running. So we simply put the main thread to sleep here. That's it."

"OK."

"Great, then here's an example of a client:"

Working with a remote object
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

"I'll explain this code line by line:"

"Line 1 is the remote object's unique name. This must be the same on both the client and the server."

"In line 6 , we create a «registry of remote objects». Its port (2099) must be the same as the port of the registry for the server application."

"On line 9, we get the object from the registry. The returned object is a proxy object and is converted to an interface. The interface must inherit the Remote marker interface."

"On line 12, we call the interface's methods as if the object was created within the same program. There's no difference."

"Cool! Now I can write distributed applications. Or games like Battleship for Android."

"Don't you dare, Amigo! The Android operating system was banned in the 27th century after its third attempt to take over the world. Robots have no access to it whatsoever. There wouldn't be any way to pull you away from it. You would start running around shouting, «Kill all the humans!»"

"Hmm. OK. But I'll still have to ask Diego. You never know, maybe he'll have something interesting to say about it."

"Then go ask him. Okay, well, until tomorrow."

"Bye, Rishi. Thanks for the interesting lesson."

Comments (3)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Lisa Level 41
13 December 2021
maybe things would work if the client doesn't create it's own, dedicated registry but loads the one from the server

            Registry registry = LocateRegistry.getRegistry("localhost", 2099); // if both are running on the same box
MaGaby2280 Level 41, Guatemala City, Guatemala
25 May 2021
😳😱😨I am sure is not that simple... My head is spinning!
BlueJavaBanana Level 37
23 January 2021
My mind is melted.