Download Topic 7 - Murdoch University

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
ICT337 Advanced Software Development
Murdoch University
Topic 7
Topic 7
RMI
 Working with sockets – A quick review
 What is RMI?
 How to use RMI?
 Developing a remote class of objects – examples
 RMI and firewalls
 JNDI
 Java IDL and CORBA
topic7.doc
Page 1
ICT337 Advanced Software Development
Murdoch University
Topic 7
Working with sockets – A quick review
Different programs can communicate through
communications channels called sockets. You can use a
socket to transfer data between unrelated processes on
the same machine or on different machines on a
network.
The TCP/IP socket is connection-oriented. When you
create a socket, you create an endpoint for a connection
between 2 processes.
You first determine the port number for the
communication.
On the server side, you create a ServerSocket object
with the selected port number as argument. You then
create a Socket object by calling the method accept()
of the ServerSocket handle. Finally, you ask the
Socket object for its input and output streams.
Since a combination of the server host name and the
selected port number above make up a unique identifier
for the server. On the client side, a Socket object can
be created using the server host name and port number.
An input stream and output stream on the client side are
created in a similar fashion.
The client can then write to its output stream to send
data to the server and read from its input stream to
retrieve data from the server. Server follows a similar
procedure to send/retrieve data to/from the client.
topic7.doc
Page 2
ICT337 Advanced Software Development
Murdoch University
Topic 7
TCP/IP socket has the following short-coming:
 It is useful only when you want to move data from
one point (machine) to another, eg. to copy the
contents of a file from System A to System B.
What if you want to directly invoke the methods of
objects located on other systems?
 You could establish a TCP/IP connection and then
send/receive messages using some predefined
format, eg. if the message from the client to the
server was “invoke computeAreaOfCircle radius 5”
then the server would execute
computeAreaOfCircle(5) and pass the result to the
client.
The drawbacks are: (1) the messages can become
complicated, (2) the messages must be specified in a
pre-defined format and a parser is required to parse
the messages, and (3) passing complex data type (eg.
Java objects) as arguments to methods is not trivial.
And… after all of your hard work, you would have
merely created a subset of the functionality already
provided by Java RMI.
topic7.doc
Page 3
ICT337 Advanced Software Development
Murdoch University
Topic 7
What is RMI?
RMI (Remote Method Invocation) is a technology that
allows programmers to directly call the methods of Java
objects that reside on other systems.
RMI is based on a similar earlier technology for
procedural programming called remote procedure calls
(RPC). The goal of RPC was to allow programmers to
concentrate on the required tasks of an application by
calling functions. RMI makes the networking
transparent to the programmer.
RMI is the Java’s implementation of RPC for Javaobject-to-Java-object distributed communication.
How to use RMI?
When using remote objects, you need only take one
additional step to locate the object within the network
after his application starts. After having the object
reference, you use it as if the object resides on the local
machine.
What happens behind the scenes is:
 The client program has a reference to a Stub object
that is a local surrogate for the remote object. This
stub is returned by the local Object Request Broker
(ORB) in response to your request to locate the
object.
topic7.doc
Page 4
ICT337 Advanced Software Development
Murdoch University
Topic 7
 The Stub object on the local system (the client side)
has all the same methods supported by the remote
object. The Stub object forwards the parameters to
the remote object and passes back any return value
for the method.
The technique used to forward the parameters to the
remote object is called marshalling, i.e. the data are
gathered and put together into a message buffer and
then organized or converted into a format that is
prescribed by a particular receiver or programming
interface. This involves serializing the parameters
into a byte stream and sent to the remote system.
NOTE: Only primitive and reference types that
implement the Serializable interface can be used as
parameter types for remote methods.
 On the remote system (the server side), a skeleton
object receives this byte stream and demarshalls to
retrieve the contents of the parameter list. This
involves deserializing the byte stream.
The skeleton object passes the parameters to the
remote object and the method is executed.
The return value (if any) from the method is
serialized and returned using the same process, but in
reverse.
topic7.doc
Page 5
ICT337 Advanced Software Development
Murdoch University
Topic 7
The diagram below shows the execution flow of a
remote method call.
local system
remote system
Stub
Skeleton
Client
Object
Remote
Object
Apparent path
Actual path
Flow of a remote method call
In RMI,
 local objects (eg. objects created locally on the client
and then passed as argument to a method on the
server) are passed by copy, ie. all data fields of the
objects are copied except for those declared as
static or transient.
 remote objects (eg. An object returned from a server
method) are passed by reference. A reference to a
topic7.doc
Page 6
ICT337 Advanced Software Development
Murdoch University
Topic 7
remote object is actually a reference to a stub, which
is a client-side proxy for the remote object.
topic7.doc
Page 7
ICT337 Advanced Software Development
Murdoch University
Topic 7
Developing a remote class of objects – An example
 STEP 1: Put all the methods of a class that you want
to expose to the clients into an interface definition.
NOTES:
o static methods cannot be part of the interface,
and neither can any data fields
o the interface must extend java.rmi.Remote,
which is a marker interface and defines no
methods
o all methods in the interface must indicate that
you may throw a java.rmi.RemoteException
Example:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
// a method sayHello with no arguments
String sayHello() throws RemoteException;
}
 STEP 2: Write the class, say HelloImpl, that
implements the above interface. Objects that require
remote behaviour should extend the class
RemoteObject, typically via the class
UnicastRemoteObject.
topic7.doc
Page 8
ICT337 Advanced Software Development
Murdoch University
Topic 7
Example:
import java.rmi.Remote;
import java.rmi.RemoteException;
public class HelloImpl
extends UnicastRemoteObject
implements Hello {
// constructor ...
// implementation for each remote method
}
By extending UnicastRemoteObject, the HelloImpl
class can be used to create a remote object that:
o uses RMI's default sockets-based transport for
communication
o runs all the time
The constructor(s) of the class must declare to throw
at least a java.rmi.RemoteException, ie.
public HelloImpl() throws RemoteException {
super();
}
The next task is to provide an implementation for
each remote method, ie. put
String sayHello() throws RemoteException {
return ”Hello world!”;
}
inside the HelloImpl class.
topic7.doc
Page 9
ICT337 Advanced Software Development
Murdoch University
Topic 7
 STEP 3: After the implementation class has been
successfully compiled, you must create the stub (for
the client side) and skeleton (for the server side)
classes required by RMI.
This can be done easily using the rmic utility
provided by Java 2 SDK on the implementation class
file. Executing the command
rmic HelloImpl
would create the Stub file HelloImpl_Stub.class
and the Skeleton file HelloImpl_Skel.class.
Note that Java 2 no longer requires the skeleton class,
so you in fact need only create the stubs for 1.2
JRMP (see later) stub protocol version, ie. use
rmic –v1.2 HelloImpl
which would create only the
file.
HelloImpl_Stub.class
 STEP 4: Write the server program that defines the
object handle(s) for the exported method declared in
the interface Hello and that does the object binding:
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
public class HelloServer {
public static void main(String args[]) {
String host = "localhost";
String port = (args.length >= 1 ? args[0] :
"1099");
System.out.println("Using port number " + port);
// (must do) Create and install a
topic7.doc
Page 10
ICT337 Advanced Software Development
Murdoch University
Topic 7
// security manager
if (System.getSecurityManager() == null)
System.setSecurityManager(
new RMISecurityManager());
try {
// create a HelloImpl object so that
// the method sayHello() can be accessed
// via the object handle.
HelloImpl obj = new HelloImpl();
// Bind this object instance to the
// name "Hi" and register it to the
// registry
Naming.rebind("//" + host + ":" + port +
"/Hi", obj);
The
HelloImpl
object (obj)
is bound to
the registry
with the
name “Hi”
System.out.println("The name Hi bound in
registry");
} catch (Exception e) {
System.out.println("HelloImpl err: " +
e.getMessage());
e.printStackTrace();
}
}
}
Because the server is opening up an interface to its
objects and allowing programs on other systems to
access these objects, for security reason, the server
program should check if a SecurityManager has been
installed and install it if one has not been installed.
Each server object will be registered on the RMI
registry under some name. The client program should
refer to each server object using the associated name. If
topic7.doc
Page 11
ICT337 Advanced Software Development
Murdoch University
Topic 7
the registered name of a server object was HelloObj
then, to access this server object, the client should refer
to //host:port/HelloObj where host is the host
address and port is the port number used.
 STEP 5: Write a client program that uses the remote
service. Below is the code for an applet:
import
import
import
import
java.applet.Applet;
java.awt.Graphics;
java.rmi.Naming;
java.rmi.RemoteException;
public class HelloApplet extends Applet {
String message = "blank";
// "obj" is the identifier that we'll use to
// refer to the remote object that implements
// the "Hello" interface
Hello obj = null;
downcasting
public void init() {
try {
The client
obj = (Hello)Naming.lookup("//" +
must look up
getCodeBase().getHost() +
the
"/Hi");
HelloImpl
// *** remote method call ***
object via the
message = obj.sayHello();
same name
that has been } catch (Exception e) {
registered by
System.out.println(
the server
"HelloApplet exception: " +
e.getMessage());
e.printStackTrace();
}
topic7.doc
Page 12
ICT337 Advanced Software Development
Murdoch University
Topic 7
}
// repaint the screen
public void paint(Graphics g) {
g.drawString(message, 25, 50);
}
}
The HTML file to encapsulate the applet is simply
<HTML>
<title>Hello World</title>
<center> <h1>Hello World</h1> </center>
<applet codebase="./"
code="HelloApplet"
width=450 height=120>
</applet>
</HTML>
NOTE: the applet must be accessible from the directory
given by the codebase parameter value
For the same security reason, a SecurityManager
should be installed if one has not been installed on the
client side.
Step 6: Compiling and running
o compile Hello.java and HelloImpl.java
o create the Stub from the HelloImpl class file via
rmic
o compile the server and the client applet
o open 3 separate MS-DOS prompt windows:
topic7.doc
Page 13
ICT337 Advanced Software Development
Murdoch University
Topic 7
 in the first window, start the registry using
the command: rmiregistry
The command rmiregistry port starts a
remote object registry on the specified port
on the current host. Default port number is
1099.
must be run in order for the
RMI server(s) to register names of objects.
rmiregistry
 in the second window, start the server
program that will construct a HelloImpl
object and register it. Two additional
parameters must be supplied to the JVM in
order for RMI to run:
1. a parameter that specifies the codebase
from which the stub and skeleton files will
be made available, eg. if these files are in
the current directory and the class files are
not put in a package then use:
-Djava.rmi.server.codebase=file:./
2. a parameter that specifies the file in which
the user security policy for the program is
located, eg. if the file is named policy in
the current directory then use:
-Djava.security.policy=policy
topic7.doc
Page 14
ICT337 Advanced Software Development
Murdoch University
Topic 7
The contents of the policy file are:
grant {
permission java.net.SocketPermission
”*:1024-65535”, ”connect,accept”;
}
which grants code loaded over the network
the permission to listen and connect on
sockets with port numbers from 1024 and
65535.
NOTE: port 1 to port 1023 are reserved
ports.
Alternatively, the contents of the policy file
could be
grant {
permission java.security.AllPermission;
}
no space
which grants all permissions.
before
and after
“=”
So, to start the server, type:
java –Djava.rmi.server.codebase=file:./
-Djava.security.policy=policy
HelloServer
 in the third window, start the client applet by
typing:
appletviewer Hello.html
or passing the URL (if one been set up) to a web
browser: http://www.it.murdoch.edu.au/
~mark/ICT337/rmi/hello/Hello.html
topic7.doc
Page 15
ICT337 Advanced Software Development
Murdoch University
Topic 7
if the class files have been placed in Mark’s
public_html directory and if rmiregistry
and HelloServer are both running on the
web server dijkstra.
The Hello example above assumes that both the
client and server are on the same machine (thus the
use of localhost). When the server is a remote
host, the client must know the host (or IP) address
and the port number used
If the client program is an application rather than an
applet provided by the server, then some class files
of the server must be accessible by the client either
via the class path or via a prior download, eg. if a
HelloClient.java application was used on the
client side, the files Hello.class and
HelloImpl_Stub.class would be required to
compile (javac) and run (java) HelloClient.java.
Parameters in RMI
In the normal Java context, parameters in RMI are pass-byvalue as you cannot change the value of the passed parameter.
Parameter passing in RMI has a different meaning. All
parameters will be passed by value, but in RMI the definitions
of parameter passing are given below.
RMI Parameter Passing
topic7.doc
Page 16
ICT337 Advanced Software Development
Murdoch University
Topic 7
RMI Pass-by-value
 The actual parameter is serialized and passed using a
network protocol to the target remote object.
Serialization essentially "squeezes" the data out of an
object/primitive.
 On the receiving end, that data is used to build a
"clone" of the original object or primitive. Note that
this process can be rather expensive if the actual
parameters point to large objects (or large graphs of
objects).
RMI Pass-by-reference
 The actual parameter, which is itself a remote object, is
represented by a proxy.
 The proxy keeps track of where the actual parameter
lives, and anytime the target method uses the formal
parameter, another remote method invocation occurs
to "call back" to the actual parameter.
 This can be useful if the actual parameter points to a
large object (or graph of objects) and there are few call
backs.
Example 2: Parameter passing example
//simple test oject------------------------------------------------import java.io.Serializable;
public class myObject implements Serializable
{
int size;
topic7.doc
Page 17
ICT337 Advanced Software Development
Murdoch University
Topic 7
String name;
public myObject()
{
size=10;
name="Your mother";
}
public myObject(int s, String n)
{
size=s;
name=n;
}
public java.lang.String getName() {
return name;
}
public void setName(java.lang.String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void output()
{
System.out.println("size= "+size+", name= "+name);
}
}
//the interface-------------------------------------------------------
topic7.doc
Page 18
ICT337 Advanced Software Development
Murdoch University
Topic 7
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface objectParams extends Remote
{
public myObject returnNewObject(myObject the)throws
RemoteException ;
public void modObject(myObject the) throws RemoteException;
}
//the interface implementation--------------------------------------------import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class myObjectImpl extends UnicastRemoteObject implements
objectParams {
public myObjectImpl() throws RemoteException
{
super();
}
public myObject returnNewObject(myObject the) throws
RemoteException
{
myObject newOj=new myObject(the.getSize(), the.getName());
newOj.setName("My mother");
return newOj;
}
public void modObject(myObject the) throws RemoteException
{
the.setName("My mother");
}
}
topic7.doc
Page 19
ICT337 Advanced Software Development
Murdoch University
Topic 7
//the RMI Server --------------------------------------------import java.rmi.Naming;
import java.rmi.RMISecurityManager;
public class myObjectServer {
public static void main(String args[]) {
/* if (System.getSecurityManager() == null)
System.setSecurityManager(
new RMISecurityManager());*/
try {
myObjectImpl mo= new myObjectImpl();
Naming.rebind("rmi://localhost/params", mo);
System.out.println("paramsServer is now running...");
} catch (Exception e) {
System.out.println("params err: " +
e.getMessage());
e.printStackTrace();
}
}
}
import java.rmi.Naming;
public class myObjectClient
{
//the RMI Client --------------------------------------------public static void main(String args[])
{
String rmiUrl="rmi://localhost/params";
try{
objectParams h=(objectParams)Naming.lookup(rmiUrl);
myObject m=new myObject();
myObject n=h.returnNewObject(m);
topic7.doc
Page 20
ICT337 Advanced Software Development
Murdoch University
Topic 7
System.out.println("original:" +m);
m.output();
System.out.println("new" +n);
n.output();
//test pass by reference
h.modObject(m);
m.output();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Run the Client and you will see that it will not change
the value of the parameter passed to the server. The
pass-by-value feature is useful only for very large
objects where serializing the whole object would
involve too much overhead.
To support pass-by-reference RMI parameters, make
your server implement your interface. I.e. to make
myObjectServer support pass-by-reference change –
public class myObjectServer {
to
public class myObjectServer implements objectParams{
Example 3
topic7.doc
Page 21
ICT337 Advanced Software Development
Murdoch University
Topic 7
See the example in the
pub/units/ICT337/Resources/DeitelCD/examples/Ch
apters/ch13/WeatherService folder, or the
corresponding folder on the textbook cd. Note that the
interface TemperatureServer.class and the stub file
TemperatureServerImpl_Stub.class must be
accessible (via CLASSPATH) to the client program
Bidirectional messaging
Clients can register themselves with the server so that
the server can call back to each client (e.g. via a hash
table containing a list of registered clients kept by the
server).
See the WeatherService example. (Optional) Compare
the example with that (more complicated) given in fig.
13.1- fig. 13.7 of the textbook.
topic7.doc
Page 22
ICT337 Advanced Software Development
Murdoch University
Topic 7
PITFALL
 It appears that the rmiregistry program must be
invoked at the same directory where the server(s)
would be started. This suggests that one should
arrange each RMI server program into a package, eg.
use the following directory structure:
rmi_1
src
rmi_2
put
Java
files
here
...
c:\ICT3
37
classes
rmi_1
put
class
files
here
rmi_2
and at the beginning of each source Java file of the
src\rmi_1 directory (say), put the line
package classes.rmi_1;
The source files should then be compiled at the root
directory c:\ICT337.
The rmiregistry utility can be invoked at the
c:\ICT337 directory.
All the servers can then be started at the same
topic7.doc
Page 23
ICT337 Advanced Software Development
Murdoch University
c:\ICT337
Topic 7
directory.
This would allow multiple rmi servers to share the
same registry.
The client needs to know the server object names
registered in the registry. It also needs to know the
type of each server object (for downcasting).
 Note that the rmiregistry program can be running
several times simultaneously. Each rmiregistry
program can be using its own, different port number.
 For examples on using packages, see files in the
hello2 folder. Note also the difference in the
makefile.
 The student folder contains a more complicated
example
 Invalid codebase parameter value and absence of the
policy file are two common errors encountered in
running RMI.
 when two different objects (from same or different
servers) are registered with the same name in the
registry, the latest registration overwrites the earlier
one (should perhaps call the bind method instead of
rebind to detect duplicated registrations).
NOTE:
topic7.doc
Page 24
ICT337 Advanced Software Development
Murdoch University
Topic 7
 multiple rmi servers sharing the same registry must
use the same port. If a different port is desired, then
another rmiregistry program with the chosen port
number specified must be invoked (recall that default
port number is 1099), eg
rmiregistery 2001
starts the registry on port 2001
RMI and firewalls
By default, RMI makes direct connections from the
client to the server. Unless the firewall is configured to
permit arbitrary connections (a pretty bad firewall), it
will not allow default RMI to work.
Since users inside the firewall often want to browse the
web outside the firewall using HTTP, most firewalls are
configured to allow HTTP requests.
Configuration involves setting up a proxy server for a
specified port.
Remote object activation
Rather than having a server running at all time (that has
objects registered) to allow client connection, remote
object activation (introduced in Java 2) supports the
topic7.doc
Page 25
ICT337 Advanced Software Development
Murdoch University
Topic 7
creation of instances of remote objects that can be
accessed by the server. This is a great improvement in
performance.
Remote object activation is managed by a small
program called rmid that runs on the server. When a
client requests a service, rmid starts the remote object
and communication proceeds normally. This allows
many services to consume processing time only when
the services are actually requested.
JNDI
The rmiregistry program is useful for small
applications but does not scale well when applications
are large and spread across many host systems.
JNDI (Java Naming and Directory Interface) is a
standard Java platform extension. It is a unified
interface to multiple naming and directory services that
already exist for enterprise development.
JNDI classes are in the packages: javax.naming,
javax.naming.directory, javax.naming.spi
Java IDL and CORBA
topic7.doc
Page 26
ICT337 Advanced Software Development
Murdoch University
Topic 7
Java RMI provides support that makes it easy to define
and use remote objects, but it only works with remote
objects that are developed using the Java programming
language. CORBA (Common Object Request Broker
Architecture) is a more generic architecture for defining
and using remote objects. It allows for the mixing of
objects developed using different programming
languages.
 Similarities between RMI and CORBA: the concepts
of stubs, skeletons, and ORBs
 Two significant differences between RMI and
CORBA:
1. the way in which the ORBs communicate with
each other.
o RMI ORBs use a protocol called the JRMP
(Java Remote Method Protocol)
o CORBA ORBs use a protocol called the IIOP
(Internet Inter-ORB Protocol), which is based
on the standard TCP/IP protocol.
Thus, RMI ORBs and CORBA ORBs cannot
communicate with each other.
2. the interfaces of CORBA objects are defined using
a special language called IDL (Interface Definition
Language). The idlj utility that comes with jdk1.4
makes it easy to generate Java interfaces and stub
and skeleton classes.
topic7.doc
Page 27
ICT337 Advanced Software Development
Murdoch University
Topic 7
CORBA will be covered in more detail in a later topic.
topic7.doc
Page 28
ICT337 Advanced Software Development
Murdoch University
Topic 7
Further reading:
 (textbook) “Advanced Java 2 Platform – How to
Program” by Deitel, Deitel, Santry, chapter 13,
sections 13.1 – sections 13.5. (Optional) See also the
case study given in section 13.6.
 JDK rmi tools:
rmic, rmiregistry
c:/jdk1.3/docs/tooldocs/tools.html#rmi
 JDK rmi tutorial:
c:/jdk1.3/docs/guide/rmi/getstart.doc.html
topic7.doc
Page 29
ICT337 Advanced Software Development
Murdoch University
Topic 7
Objectives
At the end of this topic, you should be able to
 describe the notions of client/server distributed computing
 describe the architecture of RMI
 describe the notion of stubs
 use RMI to develop classes of objects that are accessible from a
server
 compile and deploy a client/server distributed application that uses
RMI
 understand the use of JNDI and its related packages
 discover the relationship between RMI and the Java Interface
Definition Language (IDL)
topic7.doc
Page 30