5.3.8. RMI¶
5.3.8.1. Introduction¶
RMI (Remote Method Invocation) enables objects on the client Java virtual machine to invoke methods on objects in the server Java virtual machine as if calling local objects. Among them, the standard implementation of RMI is Java RMI, and there are different implementations such as Weblogic RMI and Spring RMI.
The two more important concepts in RMI are Stub and Skeleton. Stub and Skeleton implement the same set of interfaces, in which Stub is called by the client side and does not actually implement it, but communicates with the server side. Skeleton is the server side, listening to the connection from the Stub, and performing real operations according to the data sent by the Stub.
5.3.8.2. Calling Steps¶
The client invokes a method on the client helper object Stub
The client auxiliary object Stub packages the call information (variables, method names) and sends it to the server auxiliary object Skeleton through the network
The server-side auxiliary object Skeleton unpacks the information sent by the client-side auxiliary object, and finds out the method that is actually called and the object where the method is located.
Call the real method on the real service object and return the result to the server-side helper object Skeleton
The server-side helper object packs the result and sends it to the client-side helper object Stub
The client helper object unpacks the return value and returns it to the caller
Client gets return value
5.3.8.3. Examples¶
A code sample is as follows(from 《Enterprise JavaBeans》):
5.3.8.3.1. Person interface definition¶
public interface Person {
public int getAge() throws Throwable;
public String getName() throws Throwable;
}
5.3.8.3.2. Implementing Person using PersonServer¶
public class PersonServer implements Person {
private int age;
private String name;
public PersonServer(String name, int age) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
5.3.8.3.3. Implementing Person using Person_Stub¶
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
public class Person_Stub implements Person {
private Socket socket;
public Person_Stub() throws Throwable {
// connect to skeleton
socket = new Socket("computer_name", 9000);
}
public int getAge() throws Throwable {
// pass method name to skeleton
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
outStream.writeObject("age");
outStream.flush();
ObjectInputStream inStream =
new ObjectInputStream(socket.getInputStream());
return inStream.readInt();
}
public String getName() throws Throwable {
// pass method name to skeleton
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
outStream.writeObject("name");
outStream.flush();
ObjectInputStream inStream =
new ObjectInputStream(socket.getInputStream());
return (String)inStream.readObject();
}
}
5.3.8.3.4. Implementation of Skeleton¶
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.ServerSocket;
public class Person_Skeleton extends Thread {
private PersonServer myServer;
public Person_Skeleton(PersonServer server) {
// get reference of object server
this.myServer = server;
}
public void run() {
try {
// new socket at port 9000
ServerSocket serverSocket = new ServerSocket(9000);
// accept stub's request
Socket socket = serverSocket.accept();
while (socket != null) {
// get stub's request
ObjectInputStream inStream =
new ObjectInputStream(socket.getInputStream());
String method = (String)inStream.readObject();
// check method name
if (method.equals("age")) {
// execute object server's business method
int age = myServer.getAge();
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
// return result to stub
outStream.writeInt(age);
outStream.flush();
}
if(method.equals("name")) {
// execute object server's business method
String name = myServer.getName();
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
// return result to stub
outStream.writeObject(name);
outStream.flush();
}
}
} catch(Throwable t) {
t.printStackTrace();
System.exit(0);
}
}
public static void main(String args []) {
// new object server
PersonServer person = new PersonServer("Richard", 34);
Person_Skeleton skel = new Person_Skeleton(person);
skel.start();
}
}
5.3.8.3.5. Client implementation¶
public class PersonClient {
public static void main(String [] args) {
try {
Person person = new Person_Stub();
int age = person.getAge();
String name = person.getName();
System.out.println(name + " is " + age + " years old");
} catch(Throwable t) {
t.printStackTrace();
}
}
}
5.3.8.4. T3 Protocol¶
The T3 protocol is a protocol for transferring information between WebLogic servers and other types of Java programs, and is Weblogic’s implementation of the RMI specification. In simple terms, T3 can be regarded as an interface that exposes JDNI to be invoked by users.
5.3.8.5. JRMP¶
The Java Remote Method Protocol (JRMP) is a Java technology-specific protocol for finding and referencing remote objects. This is a wire-layer protocol that runs under Java Remote Method Invocation (RMI) and over TCP/IP.
JRMP is a Java-specific stream-based protocol suitable for remote calls between Java, requiring the use of Java objects on both the client and the server.