Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
INE4481 DISTRIBUTED DATABASES
& CLIENT-SERVER ARCHITECTURES
Chapter 5:
Distributed systems
with JAVA:
sockets, RMI , Threads
Rufin Soh
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Content
1.
2.
Recalls on Networking
Java Sockets
What Is a Socket?
Why Java Sockets?
Socket: Implementing a
Client
Socket: Implementing a
Server
Running the Programs
3.
4.
JAVA Threads
JAVA RMI
JAVA RMI vs other
Middlewares
Java-RMI Working mode
Programming RMI
Writing a RMI server
Wilfried Probst – Rufin Soh
5.
JAVA RMI
RMI server skeleton
Writing a RMI client
Running the client and
server
RMI and java security
Java RMI Internals
What is a codebase?
How codebase is used
RMI and Applets
RMI: multiple clients vs the
same server object
Downloading RMI stubs
RMI Command-line
examples
RMI Troubleshooting
RMI deployment examples
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Content
1.
2.
Wilfried Probst – Rufin Soh
Recalls on Networking
Java Sockets
What Is a Socket?
Why Java Sockets?
Socket: Implementing a Client
Socket: Implementing a Server
Running the Programs
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Recalls on Networking
TCP( Transport Control Protocol )
Is a connection-based protocol that provides a reliable flow of data between
two computers.
Example applications: HTTP, FTP, Telnet, SMTP.
UDP(User Datagram Protocol )
Is a protocol that sends independent packets of data, called datagrams, from
one computer to another with no guarantees about arrival.
Example applications: clock server, Ping.
Understanding Ports
The TCP and UDP protocols use ports to map incoming data to a particular
process running on a computer.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
What Is a Socket?
A socket is one endpoint of a two-way communication link between two
programs running on the network. A socket is bound to a port number so that
the TCP layer can identify the application that data is destined to be sent.
Normally, a server runs on a specific computer and has a socket that is bound to
a specific port number.
The server just waits, listening to the socket for a client to make a
connection request.
On the client-side: The client knows the hostname of the machine on which the
server is running and the port number to which the server is connected.
To make a connection request, the client tries to rendezvous with the server
on the server's machine and port.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
What Is a Socket?
If everything goes well, the server accepts the connection. Upon acceptance, the
server gets a new socket bound to a different port. It needs a new socket (and
consequently a different port number) so that it can continue to listen to the
original socket for connection requests while tending to the needs of the
connected client.
On the client side, if the connection is accepted, a socket is successfully created
and the client can use the socket to communicate with the server. Note that the
socket on the client side is not bound to the port number used to rendezvous
with the server. Rather, the client is assigned a port number local to the machine
on which the client is running.
The client and server can now communicate by writing to or reading from their
sockets.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Why Java Sockets?
You might wonder why you might choose to use sockets to communicate with
remote objects when RMI is availble? Here are two possible reasons:
To communicate with non-java objects and programs:
Not all software on networks is written in Java-- at least, not yet. Until it is, from
time to time you'll need to interface a Java program with a non-Java program.
Sockets are a good way to do this, because data transmitted over a socket is
reduced to its any languages, running on almost any platform, can deal with
a stream of bytes.
To communicate as efficiently as possible.
The convenience of RPC, RMI, and other facilities extract a price in the form
of processing overhead.
A well-designed socket interface between programs can outperform one
based on such higher-level facilities. If you server must handle large
volumes of requests, this may be important to you.
Java Socket Classes
The Java.net package provides following two classes:
Socket
ServerSocket
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Socket: Implementing a Client
Create a Socket object.
Socket Client = new Socket(?hostname,?portNumber);
Create an output stream that can be used to send info to the Socket.
PrintStream out = new PrintStream(client.getOutputStream());
Create an input stream to read the response from the server.
DataInputStream in = new DataInputStream(client.getInputStream());
Do I/O with input and output streams.
Close the socket when done.
•client.close()
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Socket: Implementing a Server
Create a SocketServer object.
ServerSocket listenSocket = new ServerSocket(portNumber).
Create a Socket object from the ServerSocket.
While (someCondition) {
Socket server = listenSocket.accept();
doSomethingWith(server);
}
Create an input stream to read input from the client.
DataInputStream in = new DataInputStream(server.getInputStream());
Create an output stream that can be used to send info back to the client.
PrintStream out = new PrintStream(server.getOutputStream());
Do I/O with input and output streams.
Close the socket when done.
Wilfried Probst – Rufin Soh
server.close()
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Running the Programs
You must start the server program first. To do this,
Run the server program using the Java interpreter, just as you would run any other Java
application. Remember to run the server on the machine that the client program
specifies when it creates the socket.
Next, run the client program. Note that you can run the client on any machine on your
network; it does not have to run on the same machine as the server.
If you are too quick, you might start the client before the server has a chance to
initialize itself and begin listening on the port. If this happens, you will see a
stack trace from the client. just restart the client.
If you forget to change the server host name in the source code for the
MySocketClient program, you will see an error message:
To keep our SocketServer example simple, we designed it to listen for and handle
a single connection request. However, multiple client requests can come into the
same port and, consequently, into the same ServerSocket object.
Client connection requests are queued at the port, so the server must accept the
connections sequentially.
However, the server can service them simultaneously through the use of threads
- one thread per each client connection.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
JAVA Threads
The basic flow of logic in a threaded server is this:
while (true) {
accept a connection ;
create a thread to deal with the client ;
end while
From a logical point of view, multithreading means multiple lines of a
single program can be executed at the same time, however, it is not the
same as starting a program twice and saying that there are multiple
lines of a program being executed at the same time.
Creating threads
Two ways of creating threads:
• implementing the runnable interface.
• Extending the Thread class is the way Java inherits methods
and variables from this parent class
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Content
1.
2.
3.
4.
Recalls on Networking
Java Sockets
JAVA Threads
JAVA RMI
JAVA RMI vs other
Middlewares
Java-RMI Working mode
Programming RMI
Writing a RMI server
RMI server skeleton
Writing a RMI client
Running the client and
server
RMI and java security
Wilfried Probst – Rufin Soh
5.
JAVA RMI
Java RMI Internals
What is a codebase?
How codebase is used
RMI and Applets
RMI: multiple clients vs
the same server object
Downloading RMI stubs
RMI Command-line
examples
RMI Troubleshooting
RMI deployment
examples
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
JAVA RMI
Remote Method Invocation (RMI) is the object equivalent of Remote
Procedure Calls (RPC).
While RPC allows you to call procedures over a network, RMI invokes
an object's methods over a network.
In the RMI model,
the server defines objects that the client can use remotely.
The clients can now invoke methods of this remote object as if it were a local
object running in the same virtual machine as the client.
RMI hides the underlying mechanism of transporting method arguments
and return values across the network.
In Java-RMI, an argument or return value can be of any primitive Java
type or any other Serializable Java object.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java-RMI Working mode
Since both the client and the server may reside on different
machines/processes, there needs to be a mechanism that can establish a
relationship between the two.
Java-RMI uses a network-based registry program called RMIRegistry to
keep track of the distributed objects. (Note: The RMI Registry is an RMI
server itself!!!)
The RMI Registry
The server object makes methods available for remote invocation by
binding it to a name in the RMI Registry.
The client object, can thus check for the availability of a certain server
object by looking up its name in the registry.
The RMI Registry thus acts as a central management point for Java-RMI.
The RMI Registry is thus a simple name repository. It does not address
the problem of actually invoking remote methods.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java-RMI Working mode
Stubs and Skeletons
Since the two objects may physically reside on different
machines, a mechanism is needed to transmit the client's request
to invoke a method on the server object to the server object and
provide a response.
Java-RMI uses an approach similar to RPC in this regard. The
code for the server object must be processed by an RMI compiler
called rmic, which is part of the JDK.
RMI System
Client Program
Server Program
Stubs & Skeletons
Stubs & Skeletons
Remote Reference layer
Remote Reference layer
Transport layer
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java-RMI Working mode
Stubs and Skeletons
The rmic compiler generates two files: a stub and a skeleton.
The stub resides on the client machine and the skeleton resides on the
server machine.
When a client invokes a server method,
•
The JVM looks at the stub to do type checking.
•
The request is then routed to the skeleton on the server,
•
Which in turn calls the appropriate method on the server object. In other words,
the stub acts as a proxy to the skeleton and the skeleton is a proxy to the actual
remote method.
RMI System
Wilfried Probst – Rufin Soh
Client Program
Server Program
Interface
Implementation
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Programming RMI
Remote Method Invocation (RMI) facilitates object function calls between Java
Virtual Machines (JVMs).
JVMs can be located on separate computers - yet one JVM can invoke
methods belonging to an object stored in another JVM.
Methods can even pass objects that a foreign virtual machine has never
encountered before, allowing dynamic loading of new classes as required.
This is a powerful feature!
Consider the follow scenario :
Developer A writes a service that performs some useful function. He regularly
updates this service, adding new features and improving existing ones.
Developer B wishes to use the service provided by Developer A. However, it's
inconvenient for A to supply B with an update every time.
Java RMI provides a very easy solution! Since RMI can dynamically load new
classes, Developer B can let RMI handle updates automatically for him. Developer A
places the new classes in a web directory, where RMI can fetch the new updates as
they are required.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Programming RMI
Connections made when client uses RMI
Firstly, the client must contact an RMI registry, and request the name of the service.
Developer B won't know the exact location of the RMI service, but he knows enough
to contact Developer A's registry. This will point him in the direction of the service he
wants to call..
Developer A's service changes regularly, so Developer B doesn't have a copy of the
class. Not to worry, because the client automatically fetches the new subclass from a
webserver where the two developers share classes. The new class is loaded into
memory, and the client is ready to use the new class. This happens transparently for
Developer B - no extra code need to be written to fetch the class.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI server
We'll create a service that can calculate the square of a number, and the
power of two numbers (238 for example).
Due to the large size of the numbers, we'll use the java.math.BigInteger class
for returning values rather than an integer or a long.
Writing an interface
The first thing we need to do is to agree upon an interface, An interface description is
a description of the methods we will allow remote clients to invoke. Let's consider
exactly what we'll need.
1.
A method that accepts as a parameter an integer, squares it, and returns a BigInteger
public BigInteger square ( int number_to_square );
2.
A method that accepts as a parameter two integers, calculates their power, and returns a
BigInteger
public BigInteger power ( int num1, int num2 );
Once we've decided on the methods that will compose our service, we have to
create a Java interface.
An interface is a method which contains abstract methods; these methods
must be implemented by another class.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI server
Here's the source code for our service (Interface) that calculates powers.
import java.math.BigInteger;
import java.rmi.*;
This is where to define
your interface
//
// PowerService Interface
//
// Interface for a RMI service that calculates powers
//
public interface PowerService extends java.rmi.Remote
{
// Calculate the square of a number
public BigInteger square ( int number )
throws RemoteException;
This is where to
define it as RMI
// Calculate the power of a number
public BigInteger power ( int num1, int num2)
throws RemoteException;
}
Our interface extends java.rmi.Remote, which indicates that this is a remote
service.
We provide method definitions for our two methods (square and power), and
the interface is complete.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI server
Implementing the interface
The next step is to implement the interface, and provide methods for the square and
power functions.
Implementing the interface is a little more tricky - we actually have to write the square
and power methods! Don't worry if you're not sure how to calculate squares and
powers, this isn't a math lesson. The real code we need to be concerned about is the
constructor and main method.
We have to declare a default constructor, even when we don't have any initialization
code for our service. This is because our default constructor can throw a
java.rmi.RemoteException, from its parent constructor in UnicastRemoteObject.
Sound confusing? Don't worry, because our constructor is extremely simple.
public PowerServiceServer () throws RemoteException
{
super();
}
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI server
Implementing the interface
Our implementation of the service also needs to have a main method. The main
method will be responsible for creating an instance of our PowerServiceServer, and
registering (or binding) the service with the RMI Registry. Our main method will also
assign a security manager to the JVM, to prevent any nasty surprises from remotely
loaded classes. In this case, a security manager isn't really needed, but in more
complex systems where untrusted clients will be using the service, it is critical.
public static void main ( String args[] ) throws Exception
{
// Assign a security manager, in the event that dynamic
// classes are loaded
if (System.getSecurityManager() == null)
System.setSecurityManager ( new RMISecurityManager() );
// Create an instance of our power service server ...
PowerServiceServer svr = new PowerServiceServer();
// ... and bind it with the RMI Registry
Naming.bind ("PowerService", svr);
System.out.println ("Service bound....");
}
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI server skeleton
Once the square and power methods are added, our server is complete. Here's the full
source code skeleton for the PowerServiceServer.
import java.math.*;
import java.rmi.*;
import java.rmi.server.*;
//
// PowerServiceServer
//
// Server for a RMI service that calculates powers
//
public class PowerServiceServer extends UnicastRemoteObject
implements PowerService
{
public PowerServiceServer () throws RemoteException
{}
// Calculate the square of a number
public BigInteger square ( int number )
throws RemoteException
{}
// Calculate the power of a number
public BigInteger power ( int num1, int num2)
throws RemoteException
{}
public static void main ( String args[] ) throws Exception
{}
}
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI client
What good is a service, if you don't write a client that uses it?
Writing clients is the easy part - all a client has to do is
•
call the registry to obtain a reference to the remote object,
•
and call its methods.
All the underlying network communication is hidden from view, which
makes RMI clients simple.
Our client must first assign a security manager, and then obtain a reference to
the service.
Note that the client receives an instance of the interface we defined earlier,
and not the actual implementation.
Some behind-the-scenes work is going on, but this is completely transparent
to the client.
// Assign security manager
if (System.getSecurityManager() == null)
{
System.setSecurityManager
(new RMISecurityManager());
} }
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Writing a RMI client
To identify a service, we specify an RMI URL.
The URL contains the hostname on which the service is located, and the logical name
of the service.
This returns a PowerService instance, which can then be used just like a local object
reference.
We can call the methods just as if we'd created an instance of the remote
PowerServiceServer ourselves.
// Call registry for PowerService
PowerService service = (PowerService) Naming.lookup("rmi://" + args[0] +
"/PowerService");
// Call remote method
System.out.println
("Answer : " + service.square(value));
// Call remote method
System.out.println
("Answer : " + service.power(value,power));
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Running the client and server
1.
Start the rmiregistry
•
Windows users should do the following (assuming that your java\bin
directory is in the current path): - start rmiregistry
•
Unix users should do the following: - rmiregistry &
2.
Compile the server
•
3.
Compile the server, and use the rmic tool to create stub files.
Start the server
•
From the directory in which the classes are located, type the following:-
•
java PowerServiceServer
4.
Start the client
•
You can run the client locally, or from a different machine. In either case,
you'll need to specify the hostname of the machine where you are running
the server. If you're running it locally, use localhost as the hostname.
•
java PowerServiceClient localhost
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI and java security
If you running the client or server with JDK1.2, then you'll need to change the
security settings.
You'll need to specify a security policy file (a sample is included with the
source code and classes) when you run the client and server.
The following changes should be made when running the server
java -Djava.security.policy=java.policy PowerServiceServer
The following changes should be made when running the client
java -Djava.security.policy=java.policy PowerServiceClient localhost
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
What is a codebase?
A codebase can be defined as a source, or a place, from which to load classes
into a Java virtual machine.
For example, if you invited a new friend over for dinner, you would need to give
that friend directions to the place where you lived, so that he or she could locate
your house.
Similarly, you can think of a codebase as the directions that you give to a JVM,
so it can find your [potentially remote] classes.
You can think of your CLASSPATH as a "local codebase", because it is the list of
places on disk from which you load local classes.
When loading classes from a local disk-based source, your CLASSPATH variable
is consulted.
Your CLASSPATH can be set to take either relative or absolute path names to
directories and/or archives of class files.
So just as CLASSPATH is a kind of "local codebase", the codebase used by
applets and remote objects can be thought of as a "remote codebase".
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
How codebase is used in general
To interact with an applet, that applet and any classes that it needs to run must be
accessible by remote clients.
While applets can be accessed from "ftp://" or local "file:///" URLs, they are usually accessed
from a remote HTTP server.
1.
The client browser requests an applet class that is not found in the client's CLASSPATH
2.
The class definition of the applet (and any other class(es) that it needs) is downloaded from
the server to the client using HTTP
3.
The applet executes on the client
An HTML source to invoke an applet will contain something like:
<applet height=100 width=100 codebase="myclasses/" code="My.class">
<param name="ticker"> </applet>
The applet's codebase is always relative to the URL of the HTML page in which the <applet>
tag is contained.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
How codebase is used in RMI
Using RMI, applications can create remote objects that accept method calls from
clients in other JVMs.
In order for a client to call methods on a remote object, the client must have a
way to communicate with the remote object.
Rather than having to program the client to speak the remote object's protocol,
RMI uses special classes called stubs that can be downloaded to the client that
are used to communicate with (make method calls on) the remote object.
The java.rmi.server.codebase property value represents one or more URL
locations from which these stubs (and any classes needed by the stubs) can be
downloaded.
Like applets, the classes needed to execute remote method calls can be
downloaded from "file:///" URLs, but like applets, a "file:///" URL generally
requires that the client and the server reside on the same physical host, unless
the file system referred to by the URL is made available using some other
protocol, such as NFS.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java RMI Internals
•
The RMI Server creates an instance of the 'Server Object' which extends UnicastRemoteObject
•
1.
The constructor for UnicastRemoteObject "exports" the Server Object - basically making
it available to service incoming RMI calls. A TCP socket which is bound to an arbitrary
port number is created and a thread is also created that listens for connections on that
socket.
The server registers the server object with the registry. This operation actually hands the
client-side "stub" for that server object. This stub contains the information needed to "call
back" the server when it is invoked (such as the hostname/port of the server listening socket).
Registry
3 RMI
Client
RMI
HTTP URL
1
RMI Server
HTTP URL
Web server
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java RMI Internals
2.
3.
4.
A client obtains this stub by calling the registry, which hands it the stub directly.
This is also where the "codebase" comes in: If the server specified a "codebase" to use for
clients to obtain the classfile for the stub, this will be passed along to the client via the
registry.
The client can then use the codebase to resolve the stub class - that is, to load the stub
classfile itself).
•
That is all that the RMIRegistry really does: It holds onto remote object stubs which it
can hand off to clients when requested.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java RMI Internals
5.
When the client issues a remote method invocation to the server, the stub class
creates a "RemoteCall" which basically
(a) opens a socket to the server on the port specified in the stub itself, and
(b) Sends the RMI header information as described in the RMI spec.
6.
The stub class marshalls the arguments over the connection by using methods on
RemoteCall to obtain the output stream which basically returns a subclass of
ObjectOutputStream which knows how to deal with passing objects which extend
java.rmi.Remote, which serializes Java objects over the socket
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
Java RMI Internals
7.
The stub class calls RemoteCall.executeCall which causes the RMI to happen.
8.
On the server side, when a client connects to the server socket, a new thread is
forked to deal with the incoming call. The original thread can continue listening to
the original socket so that additional calls from other clients can be made.
9.
The server reads the header information and creates a RemoteCall of its own to
deal with unmarshalling the RMI arguments from the socket.
10.
The server calls the "dispatch" method of the skeleton class (the server-side "stub"
generated by rmic), which calls the appropriate method on the object and pushes
the result back down the wire (using the same 'RemoteCall' interface which the
client used to marshall the arguments). If the server object threw an exception then
the server catches this and marshalls that down the wire instead of the return
value.
11.
Back on the client side, the return value of the RMI is unmarshalled (using the
RemoteCall created in step 5 above) and returned from the stub back to the client
code itself. If an exception was thrown from the server that's unmarshalled and rethrown from the stub.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI: multiple clients vs the same server
object
All the Clients get stubs which contain the same hostname/port number as the
server-side socket which is listening for calls on the object.
When a client connects, the server forks a new thread to deal with the
incoming request, but keeps listening to that original socket (in another
thread) so that other calls can be made.
There doesn't appear to be any synchronization within the server side
components - if multiple clients simultaneously call into the server object they
can all manipulate the server object state at the same time.
You can of course make methods in your server object "synchronized" to
synchronize access to them.
Now, the RMI specification defines both a "single op" and a "stream" protocol
for RMI calls. The former allows a single RMI call to be made on a socket
which is then closed; the latter allows multiple RMI calls to be issued on the
same socket one after the other.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI: multiple clients vs the same server
object
Sun's RMI implementation appears to be using this latter mechanism which
means that a single client-side stub object will open a single socket to the
server for all of its communication.
Multiple stubs within the same JVM or different JVMs on the same host will
each have their own socket to the server (which might all dispatch calls to the
same server-side object). The net result is that each time you obtain a stub
(from the registry) for a particular server-side object, you will eventually
create a new socket to talk to the server.
So basically:
ON THE SERVER: A single 'UnicastRemoteObject' which ends up creating
multiple threads to listen for calls on this single object - one thread per socket
(basically meaning one thread per client)
ON THE CLIENT: One socket to the server per stub, meaning that if the client
has multiple stubs pointing to the same server object it will have multiple
sockets open to that server.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI and Applets
A remote system can run a program, for example an applet, which has never
been installed on its disk
For example, a JVM running from within a web browser can download the
bytecodes for subclasses of java.applet.Applet and any other classes needed by
that applet.
The system on which the browser is running has most likely never run this
applet before, nor installed it on its disk. Once all the necessary classes have
been downloaded from the server, the browser can start the execution of the
applet program using the local resources of the system on which the client
browser is running.
For the first few sections of this document, codebase with regard to applets will
be discussed in order to help describe codebase with regard to Java Remote
Method Invocation (RMI).
Java RMI takes advantage of this capability to download and execute classes
and on systems where those classes have never been installed on disk.
Using the RMI API any JVM, not only those in browsers, can download any Java
class file including specialized RMI stub classes, which enable the execution of
method calls on a remote server using the server system's resources.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI and Applets
The notion of a codebase originates from the use of ClassLoaders in the Java
programming language.
When a Java program uses a ClassLoader, that class loader needs to know the
location(s) from which it should be allowed to load classes.
Usually, a class loader is used in conjunction with an HTTP server that is serving
up compiled classes for the Java platform.
The first ClassLoader/codebase pairing that you came into contact with was the
AppletClassLoader, and the "codebase" part of the <applet> HTML tag
An HTML source to invoke an applet will contain something like:
<applet height=100 width=100 codebase="myclasses/" code="My.class">
<param name="ticker">
</applet>
to invoke a servlet will contain something like:
<servlet codebase="myclasses/" code="My.class">
<param name="ticker">
</servlet>
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI development steps
The development process is shown bellow where Bob is the server
developer and Alice the client one.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI development steps
The different steps Bob must follow to get his server implemented and running are:
1.
Define the server interface. The server object declares its service via a remote
interface, that must therefore extends the java.rmi.Remote interface.
2.
Write the server code. Bob must provide the Java file containing the server class that
implements its server interface, and that inherits from the
java.rmi.UnicastRemoteObject class. He must also include the code that will install a
SecurityManager and that will register the server interface within the RMI naming
context using the Naming.bind (or rebind) method. The daemon program that is in
charge of the naming service is rmiregistry, and it must of course be running for the
interface registration to succeed(Recall: the RMIregistry is a server itself).
3.
Compile the server class. Bob first uses the javac compiler to produce the server
.class file, and secondly, runs the rmic compiler to obtain the stub and skeleton .class
files.
4.
Execute the server program. If the rmiregistry daemon is not already running, Bob
must launch it. He can then run the java interpreter with his server .class file.
5.
Distribute the stub class. In order to get clients calling the methods of his server, Bob
needs to give them the stub class he has just generated, to Alice for example. This will
enable her code to make successful requests on his server object.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Command-line examples
In the case of an applet, the applet codebase value is embedded in an HTML
page, as we saw in the HTML example ..
In the case of Java RMI codebase, rather than having a reference to the class
embedded in an HTML page, the client first contacts the RMI registry for a
reference to the remote object. Because the remote object's codebase can refer
to any URL, not just one that is relative to a known URL,
The value of the RMI codebase must be an absolute URL to the location of the
stub class and any other classes needed by the stub class. This value of the
codebase property can refer to:
The URL of a directory in which the classes are organized in package-named
sub-directories
The URL of a JAR file in which the classes are organized in package-named
directories
A space-delimited string containing multiple instances of JAR files and/or
directories that meet the criteria above
Note: When the codebase property value is set to the URL of a directory, the
value must be terminated by a "/".
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Command-line examples
Examples
If the location of your downloadable classes is on an HTTP server named "webvector",
in the directory "export" (under the web root), your codebase property setting might
look like this:
-Djava.rmi.server.codebase=http://webvector/export/
If the location of your downloadable classes is on an HTTP server named "webline", in a
JAR file named "mystuff.jar", in the directory "public" (under the web root), your
codebase property setting might look like this:
-Djava.rmi.server.codebase=http://webline/public/mystuff.jar
Now let's suppose that the location of your downloadable classes has been split
between two JAR files, "myStuff.jar" and "myOtherStuff.jar". If these JAR files are
located on different servers (named "webfront" and "webwave"), your codebase
property setting might look like this:
-Djava.rmi.server.codebase="http://webfront/myStuff.jar http://webwave/myOtherStuff.jar"
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Troubleshooting
Any serializable class, including RMI stubs, can be downloaded if your RMI
programs are configured properly. Here are the conditions under which dynamic
stub downloading will work:
A.
B.
C.
D.
The stub class and any of the classes that the stub relies on are served up from a URL
reachable from the client.
The java.rmi.server.codebase property has been set on the server program (or in the case
of activation, the "setup" program) that makes the call to bind or rebind, such that:
•
The value of the codebase property is the URL in step A and
•
If the URL specified as the value of the codebase property is a directory, it must end
in a trailing "/"
The rmiregistry cannot find the stub class or any of the classes that the stub relies on in
its CLASSPATH. This is so the codebase gets annotated to the stub when the registry
does its class load of the stub, as a result of calls to bind or rebind in the server or setup
code.
The client has installed a SecurityManager that allows the stub to be downloaded. In the
Java 2 SDK, Standard Edition, v 1.2 this means that the client must also have a properly
configured security policy file.
There are two common problems associated with the java.rmi.server.codebase
property, which are discussed next.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Troubleshooting
If you encounter a problem running your RMI server
Receipt of a ClassNotFoundException when attempting to bind or rebind a remote object
to a name in the registry. This exception is usually due to a malformed codebase
property, resulting in the registry not being able to locate the remote object's stubs or
other classes needed by the stub.
It is important to note that the remote object's stub implements all the same interfaces
as the remote object itself, so those interfaces, as well as any other custom classes
declared as method parameters or return values, must also be available for download
from the specified codebase.
Most frequently, this exception is thrown as a result of omitting the trailing slash from
the URL value of the property. Other reasons would include: the value of the property is
not a URL; the path to the classes specified in the URL is incorrect or misspelled; the
stub class or any other necessary classes are not all available from the specified URL.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Troubleshooting
The exception that you may encounter in such a case would look like this:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Compiled Code)
at sun.rmi.transport.StreamRemoteCall.executeCall(Compiled Code)
at sun.rmi.server.UnicastRef.invoke(Compiled Code)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Compiled Code)
at java.rmi.Naming.rebind(Compiled Code)
at examples.callback.MessageReceiverImpl.main(Compiled Code)
RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
If you encounter a problem running your RMI client
The second problem you could encounter is the receipt of a ClassNotFoundException when attempting
to lookup a remote object in the registry. If you receive this exception in a stacktrace resulting from an
attempt to run your RMI client code, then your problem is the CLASSPATH with which your RMI
registry was started. Here is what the exception will look like:
java.rmi.UnmarshalException: Return value class not found; nested exception is:
java.lang.ClassNotFoundException: MyImpl_Stub
at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:109
at java.rmi.Naming.lookup(Naming.java:60)
at RmiClient.main(MyClient.java:28)
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Troubleshooting
This is a list of some Exceptions that may occur During Remote Object Export
When a remote object class is created that extends UnicastRemoteObject, the object is exported,
meaning it can receive calls from external Java virtual machines and can be passed in an RMI
call as either a parameter or return value. An object can either be exported on an anonymous
port or on a specified port. For objects not extended from UnicastRemoteObject, the
java.rmi.server.UnicastRemoteObject.exportObject method is used to explicitly export the object.
Exception
Context
Class of stub not found.
Name collision with class of same name as stub
causes one of these errors:
· Stub can't be instantiated
· Stub not of correct class
Bad URL due to wrong codebase.
Stub not of correct class.
java.rmi.StubNotFoundException
Exception
Context
java.rmi.server.SkeletonNotFoundException
Class of skeleton not found.
note: this exception is deprecated as of Java 2 SDK, Standard
Edition, v1.2
Name collision with class of same name as skeleton
causes one of these errors:
Skeleton can't be instantiated
Skeleton not of correct class
Bad URL due to wrong codebase. Skeleton not of correct
class.
java.rmi.server.ExportException
Wilfried Probst – Rufin Soh
The port is in use by another VM.
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI Troubleshooting
Exception
Context
java.rmi.UnknownHostException
Unknown host.
java.rmi.ConnectException
Connection refused to host.
java.rmi.ConnectIOException
Connection refused to host.
java.rmi.MarshalException
I/O error creating connection.
java.rmi.StubNotFoundException
Attempt to invoke a method on an object that is no longer
available.
java.rmi.NoSuchObjectException
I/O error marshaling transport header, marshaling call
header, or marshaling arguments.
java.rmi.activation.ActivateFailedException
Thrown by RMI runtime when activation fails during a
remote call to an activatable object
java.rmi.ServerError
Any error that occurs while the server is executing a remote
method. The ServerError exception object contains the
underlying error that was thrown by the server,
Operation disallowed. The registry restricts bind, rebind, and
unbind to the same host. The lookup operation can originate
from any host.
java.rmi.AccessException
java.rmi.NotBoundException
Wilfried Probst – Rufin Soh
Attempt to look up a name that is not bound.
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
JAVA RMI vs other Middlewares
Java-RMI is a Java-specific middleware that allows client Java programs to
invoke server Java objects as if they were local.
Java-RMI is tightly coupled with the Java language. Hence there are no
separate IDL mappings that are required to invoke remote object methods.
This is different from DCOM or CORBA where IDL mappings have to be
created to invoke remote methods.
Since Java-RMI is tightly coupled with The Java Language, Java-RMI can
work with true sub-classes. Neither DCOM nor CORBA can work with true
subclasses since they are static object models
Because of this, parameters passed during method calls between machines
can be true Java Objects. This is impossible in DCOM or CORBA at present.
If a process in an RMI system receives an object of a class that it has never
seen before, it can request that its class information be sent over the network.
Over and above all this, Java-RMI supports Distributed Garbage Collection
that ties into the local Garbage Collectors in each JVM.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI deployment examples
Each main functionality are designed as a totally independent system based on
this architecture:
o PRESENTATION,
o ACQUISITION,
o ACCESS
each functionality is a standalone system which can be used for another goal.
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI deployment examples
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES
RMI deployment examples
Wilfried Probst – Rufin Soh
INE4481 DISTRIBUTED DATABASES & CLIENT-SERVER ARCHITECTURES