Remote Method Invocation
Ø A primary
goal of RMI is to allow programmers to develop distributed Java programs
Ø RMI is
the Java Distributed Object Model for facilitating communications among
distributed objects
Ø RMI is a
higher-level API built on top of sockets
Ø Socket-level
programming allows you to pass data through sockets among computers
Ø RMI
enables you not only to pass data among objects on different systems, but also
to invoke methods in a remote object
The
Differences between RMI and Traditional Client/Server Approach
·
RMI component can act as both a client and a
server, depending on the scenario in question.
·
RMI system can pass functionality from a server to a
client and vice versa. A client/server system typically only passes data back
and forth between server and client.
Interfaces
·
In RMI, the definition of a
remote service is coded using a Java interface.
·
The implementation of the remote
service is coded in a class
·
The key to understanding RMI is
to remember that interfaces define behavior and classes define implementation.
RMI supports two classes:
1. The first class is the implementation of the behavior, and it runs on the server.
2. The second class acts as a proxy for the remote service and it runs on the client.
A client program makes method calls on the proxy object, RMI sends the request to the remote JVM, and forwards it to the implementation. Any return values provided by the implementation are sent back to the proxy and then to the client's program.
RMI Architecture Layers
The RMI implementation is built from three abstraction layers.
Ø The first is the Stub and Skeleton layer. This layer intercepts method
calls made by the client to the interface reference variable and redirects
these calls to a remote RMI service.
Ø The next layer is the Remote Reference Layer. This layer understands how
to interpret and manage references made from clients to the remote service
objects. In JDK 1.1, this layer connects clients to remote service objects that
are running and exported on a server. The connection is a one-to-one (unicast)
link. In the Java 2 SDK, this layer was enhanced to support the activation of
dormant remote service objects via Remote Object Activation.
Ø The Transport Layer is based on TCP/IP connections between machines in a
network. It provides basic connectivity, as well as some firewall penetration
strategies.
1.
A server object is registered
with the RMI registry;
2.
A client looks through the RMI
registry for the remote object;
3.
Once the remote object is
located, its stub is returned in the client;
4.
The remote object can be used in
the same way as a local object. The communication between the client and the
server is handled through the stub and skeleton
Stub and Skeleton Layer
In this layer, RMI uses the Proxy design pattern. In the Proxy pattern,
an object in one context is represented by another (the proxy) in a separate
context. The proxy knows how to forward method calls between the participating
objects. The following class diagram illustrates the Proxy pattern.
In RMI's use of the Proxy pattern, the stub class
plays the role of the proxy, and the remote service implementation class plays
the role of the RealSubject.
A skeleton is a helper class that is generated for RMI to use. The
skeleton understands how to communicate with the stub across the RMI link. The
skeleton carries on a conversation with the stub; it reads the parameters for
the method call from the link, makes the call to the remote service
implementation object, accepts the return value, and then writes the return
value back to the stub.
Remote Reference Layer
The Remote Reference Layers defines and supports the invocation
semantics of the RMI connection. This layer provides a RemoteRef object that
represents the link to the remote service implementation object.
The stub objects use the invoke() method in RemoteRef to forward the
method call. The RemoteRef object understands the invocation semantics for
remote services.
The JDK 1.1 implementation of RMI provides only one way for clients to
connect to remote service implementations: a unicast, point-to-point
connection. Before a client can use a remote service, the remote service must
be instantiated on the server and exported to the RMI system.
The Java 2 SDK implementation of RMI adds a new
semantic for the client-server connection. In this version, RMI supports
activatable remote objects. When a method call is made to the proxy for an
activatable object, RMI determines if the remote service implementation object
is dormant. If it is dormant, RMI will instantiate the object and restore its
state from a disk file. Once an activatable object is in memory, it behaves
just like JDK 1.1 remote service implementation objects.
Transport Layer
The Transport Layer makes the connection between JVMs. All connections
are stream-based network connections that use TCP/IP. Even if two JVMs are
running on the same physical computer, they connect through their host
computer's TCP/IP network protocol stack. The following diagram shows the
unfettered use of TCP/IP connections between JVMs.
As you know, TCP/IP provides a persistent, stream-based connection
between two machines based on an IP address and port number at each end.
Usually a DNS name is used instead of an IP address; this means you could talk
about a TCP/IP connection between flicka.magelang.com:3452 and rosa.jguru.com:4432.
In the current release of RMI, TCP/IP connections are used as the foundation
for all machine-to-machine connections.
On top of TCP/IP, RMI uses a wire level protocol called Java Remote
Method Protocol (JRMP). JRMP is a proprietary, stream-based protocol that is
only partially specified is now in two versions. The first version was released
with the JDK 1.1 version of RMI and required the use of Skeleton classes on the
server. The second version was released with the Java 2 SDK. It has been optimized
for performance and does not require skeleton classes.Some other changes with
the Java 2 SDK are that RMI service interfaces are not required to extend from
java.rmi.Remote and their service methods do not necessarily throw
RemoteException.
RMI can use many different directory services, including the Java Naming
and Directory Interface (JNDI). RMI itself includes a simple service called the
RMI Registry, rmiregistry. The RMI Registry runs on each machine that hosts
remote service objects and accepts queries for services, by default on port
1099.
On a host machine, a server program creates a remote service by first
creating a local object that implements that service. Next, it exports that
object to RMI. When the object is exported, RMI creates a listening service
that waits for clients to connect and request the service. After exporting, the
server registers the object in the RMI Registry under a public name.
On the client side, the RMI Registry is accessed through the static
class Naming. It provides the method lookup() that a client uses to query a
registry. The method lookup() accepts a URL that specifies the server host name
and the name of the desired service. The method returns a remote reference to
the service object. The URL takes the form:
rmi://<host_name>
[:<name_service_port>]
/<service_name>
where the host_name is a name recognized on the local area network (LAN)
or a DNS name on the Internet. The name_service_port only needs to be specified
only if the naming service is running on a different port to the default 1099.
Build a simple remote calculator service and use it from a client
program.
A working RMI system is composed of several parts.
Ø Interface definitions for the remote services
Ø
Implementations
of the remote services
Ø
Stub and
Skeleton files
Ø
A server
to host the remote services
Ø
An RMI
Naming service that allows clients to find the remote services
Ø
A class
file provider (an HTTP or FTP server)
Ø
A client
program that needs the remote services
To simplify things, you will use a single directory
for the client and server code. By running the client and the server out of the
same directory, you will not have to set up an HTTP or FTP server to provide
the class files.Assuming that the RMI system is already designed, you take the
following steps to build a system:
1.
Write and compile Java code for
interfaces
2.
Write and compile Java code for
implementation classes
3.
Generate Stub and Skeleton class
files from the implementation classes
4.
Write Java code for a remote
service host program
5.
Develop Java code for RMI client
program
6.
Install and run RMI system
1.
Interfaces: First, write and compile the Java
code for the service interface. The Calculator
interface defines all of the remote features offered by the service:
public interface Calculator extends java.rmi.Remote {
public long add(long a, long b)
throws java.rmi.RemoteException; public long sub(long a, long b) throws
java.rmi.RemoteException; public long mul(long a, long b) throws
java.rmi.RemoteException; public long div(long a, long b) throws
java.rmi.RemoteException; }
2.
Implementation
Next, write the implementation for the remote service. This is the
CalculatorImpl class:
public class CalculatorImpl extends
java.rmi.server.UnicastRemoteObject
implements Calculator {
//Implementations must have an explicit constructor
in order to declare the
//RemoteException exception
public CalculatorImpl() throws
java.rmi.RemoteException {
super(); }
public long add(long a, long b) throws
java.rmi.RemoteException { return a + b; }
public long sub(long a, long b) throws
java.rmi.RemoteException { return a - b;
}
public long mul(long a, long b) throws
java.rmi.RemoteException { return a * b; }
public long div(long a, long b) throws
java.rmi.RemoteException { return a / b;
} }
The implementation class uses UnicastRemoteObject to link into the RMI
system. In the example the implementation class directly extends
UnicastRemoteObject. This is not a requirement. A class that does not extend
UnicastRemoteObject may use its exportObject() method to be linked into RMI.
When a class extends UnicastRemoteObject, it must provide a constructor
that declares that it may throw a RemoteException object. When this constructor
calls super(), it activates code in UnicastRemoteObject that performs the RMI
linking and remote object initialization.
3. Stubs and Skeletons: You next use the RMI compiler, rmic, to generate the stub and skeleton files. The compiler runs on the remote
service implementation class file.
>rmic CalculatorImpl
4. Host Server: Remote RMI services must be hosted in a server process. The class CalculatorServer is a very simple
server that provides the bare essentials for hosting.
import java.rmi.Naming;
public class CalculatorServer {
public CalculatorServer() {
try {
Calculator c = new CalculatorImpl();
Naming.rebind("rmi://localhost:1099/CalculatorService",
c);
} catch (Exception e) { System.out.println("Trouble: " + e); } }
public
static void main(String args[]) { new CalculatorServer(); } }
5.Client The source code for the client follows:
import java.rmi.Naming; import java.rmi.RemoteException;
import java.net.MalformedURLException; import
java.rmi.NotBoundException; public class CalculatorClient {
public static void main(String[]
args) { try {
Calculator c = (Calculator)
Naming.lookup("rmi://localhost/CalculatorService");
System.out.println( c.sub(4, 3) );
System.out.println( c.add(4, 5) );
System.out.println( c.mul(3, 6) ); System.out.println( c.div(9, 3) );
}
catch (MalformedURLException murle) {
System.out.println();
System.out.println("MalformedURLException");
System.out.println(murle); }
catch (RemoteException re) {
System.out.println();
System.out.println("RemoteException");
System.out.println(re); }
catch (NotBoundException nbe) {
System.out.println();
System.out.println("NotBoundException");
System.out.println(nbe); }
catch ( java.lang.ArithmeticException ae) {
System.out.println();
System.out.println("java.lang.ArithmeticException");
System.out.println(ae); } } }
6.Running the RMI System
You are now ready to run the system! You need to start three consoles,
one for the server, one for the client, and one for the RMIRegistry.
Start with the Registry. You must be in the directory that contains the
classes you have written. From there, enter the following: > rmiregistry
If all goes well, the registry will start running and you can switch to
the next console.
In the second console start the server hosting the CalculatorService,
and enter the following:
>java CalculatorServer
It will start, load the implementation into memory and wait for a client
connection.
In the last console, start the client program. >java CalculatorClient
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.