RMI - PowerPoint PPT Presentation

1 / 112
About This Presentation
Title:

RMI

Description:

http://java.sun.com/developer/onlineTraining/rmi/RMI.html. And ... This is a full-fledged RMI system. Screenshot of calculator ... – PowerPoint PPT presentation

Number of Views:199
Avg rating:3.0/5.0
Slides: 113
Provided by: higg2
Category:
Tags: rmi | fledged | javac | recompile

less

Transcript and Presenter's Notes

Title: RMI


1
RMI
  • From OReilly RMI text and internet tutorials

2
Other rmi tutorials
  • http//java.sun.com/developer/onlineTraining/rmi/R
    MI.html
  • And
  • http//java.sun.com/docs/books/tutorial/rmi/

3
RMI
  • The Java Remote Method Invocation (RMI) system
    allows an object running in one Java Virtual
    Machine (VM) to invoke methods on an object
    running in another Java VM. RMI provides for
    remote communication between programs written in
    the Java programming language.

4
A little background
  • Your RMI application will consist of several
    files, generally.
  • Server side usually at least two files
  • An interface which implements remote and which
    defines a function (or more)
  • A class implementing the interface
  • Maybe a separate server which registers the
    remote services and delivers them to clients
  • Client-side applet or html or servlet to deliver
    requested method invocations

5
A little background
  • Since the client needs to know the name of, and
    signature of, the method she invokes, a method
    stub file needs to be available to the client
    (in the class path for client) showing how to
    marshal and unmarshal parameters and return
    types.
  • The rmi compiler (rmic in your java directory)
    creates someclass_stub.class files which are
    provided to your client.

6
Port for rmi
  • To run registry on Windows platforms
  • start rmiregistry
  • By default, the registry runs on TCP port 1099.
    To start a registry on a different port, specify
    the port number from the command line. For
    example, to start the registry on port 2001 on a
    Windows platform
  • start rmiregistry 2001

7
First a tutorial example
  • http//java.sun.com/j2se/1.5.0/docs/guide/rmi/hell
    o/hello-world.html51
  • A VERY simple working rmi example

8
Hello interface(extends remote)
  • package example.hello
  • import java.rmi.Remote
  • import java.rmi.RemoteException
  • public interface Hello extends Remote
  • String sayHello() throws RemoteException

9
Client
  • package example.hello
  • import java.rmi.registry.LocateRegistry//usual
    RMI imports
  • import java.rmi.registry.Registry
  • public class Client
  • private Client()
  • public static void main(String args)
  • String host (args.length lt 1) ? null
    args0
  • try
  • Registry registry LocateRegistry.getRegistr
    y(host)
  • Hello stub (Hello) registry.lookup("Hello")
  • String response stub.sayHello()
  • System.out.println("response " response)
  • catch (Exception e)
  • System.err.println("Client exception "
    e.toString())
  • e.printStackTrace()

10
The RMI Server (sometimes called
ServiceImpllike HelloImpl in this case)
  • package example.hello
  • import java.rmi.registry.Registry
  • import java.rmi.registry.LocateRegistry
  • import java.rmi.RemoteException
  • import java.rmi.server.UnicastRemoteObject
  • public class Server implements Hello
  • public Server()
  • public String sayHello()
  • return "Hello, world!"
  • public static void main(String args)
  • try
  • Server obj new Server()
  • Hello stub (Hello) UnicastRemoteObject.expo
    rtObject(obj, 0)
  • // Bind the remote object's stub in the
    registry
  • Registry registry LocateRegistry.getRegistr
    y()
  • registry.bind("Hello", stub)
  • System.err.println("Server ready")
  • catch (Exception e)
  • System.err.println("Server exception "
    e.toString())

11
Compile then run
  • First compile Hello.java, then the other two
    files.
  • Start rmiregistry
  • Run server
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjava
    example/hello/Server
  • Response is Server ready
  • Run client
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjava
    example/hello/Client
  • response Hello, world!

12
Same interfacebut using an applet
  • The impl file
  • import java.rmi.Naming
  • import java.rmi.RemoteException
  • import java.rmi.RMISecurityManager
  • import java.rmi.server.UnicastRemoteObject
  • public class HelloImpl extends
    UnicastRemoteObject implements Hello
  • public HelloImpl() throws RemoteException
  • super()
  • public String sayHello()
  • return "Hello World!"
  • public static void main(String args)
  • // Create and install a security manager
  • if (System.getSecurityManager() null)
  • System.setSecurityManager(new
    RMISecurityManager())
  • try
  • HelloImpl obj new HelloImpl()

13
The policy file
  • JRE did not seem to look at the
    jre/lib/security/java.policy file in the JRE
    directory so I used my own policy file
  • grant
  • //to handle rmi connection issues
  • permission java.net.SocketPermission
    "localhost1024-", "listen,connect,resolve"

14
Run the impl file specifying policy at runtime
  • c\PROGRA1\Java\JDK151.0_0\bingtjava
    -Djava.security.manager -Djava.security.policypol
    icy.all HelloImpl
  • HelloServer bound in registry

15
Hello applet rmi example files
  • Hello.htmlusual file points to applet.class, I
    put it in webapps/ROOT
  • HelloApplet a jdk1.1 applet that gets a HelloInt
    object bound in the registry
  • HelloImpl remote thingy implementing the hello
    interface.
  • Remember to javac and rmic the HelloImpl file and
    put both the class and the stub class files in
    the directory with your applet code
  • I did not use packages from the example and had
    to modify a few other minor items.

16
RMI
  • I started RMI registry from my java directory,
    not from tomcat.
  • I did not use a policy file for the application
    program.
  • I ran the example in Netscape not IE
  • A batchfile to set classpath to some webapp and
    then start rmi
  • Set classpathC\PROGRA1\TOMCAT1.5\WEBAPPS\ROOT
  • C\PROGRA1\TOMCAT1.5\WEBAPPS\ROOT\WEB-INF\classe
    s
  • rmiregistry

17
The tutorial url for this example
  • http//java.sun.com/j2se/1.3/docs/guide/rmi/getsta
    rt.doc.html5238

18
Run the applet (the little hello world is the
message)
19
Windows rmi info
  • rmiregistry - The Java Remote Object Registry
  • The rmiregistry command starts a remote object
    registry on the specified port on the current
    host.
  • rmiregistry port
  • The rmiregistry command creates and starts a
    remote object registry on the specified port on
    the current host. If port is omitted, the
    registry is started on port 1099. The rmiregistry
    command produces no output and is typically run
    in the background. For example start rmiregistry

20
Windows rmi info
  • A remote object registry is a bootstrap naming
    service that is used by RMI servers on the same
    host to bind remote objects to names. Clients on
    local and remote hosts can then look up remote
    objects and make remote method invocations.
  • The registry is typically used to locate the
    first remote object on which an application needs
    to invoke methods. That object in turn will
    provide application-specific support for finding
    other objects.

21
Windows rmi info
  • The methods of the java.rmi.registry.LocateRegistr
    y class are used to get a registry operating on
    the local host or local host and port.
  • The URL-based methods of the java.rmi.Naming
    class operate on a registry and can be used to
    look up a remote object on any host, and on the
    local host bind a simple (string) name to a
    remote object, rebind a new name to a remote
    object (overriding the old binding), unbind a
    remote object, and list the URLs bound in the
    registry.
  • OPTIONS
  • -J
  • Used in conjunction with any java option, it
    passes the option following the -J (no spaces
    between the -J and the option) on to the java
    interpreter.
  • SEE ALSO
  • java, java.rmi.registry.LocateRegistry and
    java.rmi.Naming

22
The calculator project interface file
  • 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

23
The calculator project implementation 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

24
The calculator project run rmic on
CalculatorImpl to generate stub file
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtdir
    Calculator.
  • Volume in drive C has no label.
  • Volume Serial Number is 84F7-99D3
  • Directory of c\PROGRA1\Java\JDK151.0_0\bin
  • 10/24/2006 0133 PM 271
    Calculator.class
  • 10/24/2006 0133 PM 405
    Calculator.java
  • 10/24/2006 0135 PM 536
    CalculatorImpl.class
  • 10/24/2006 0135 PM 815
    CalculatorImpl.java
  • 10/24/2006 0137 PM 2,476
    CalculatorImpl_Stub.class
  • 5 File(s) 4,503 bytes
  • 0 Dir(s) 142,396,870,656 bytes
    free
  • C\PROGRA1\JAVA\JDK151.0_0\BINgt

25
The calculator project the server for the rmi
  • import java.rmi.Naming
  • public class CalculatorServer
  • public CalculatorServer()
  • try
  • Calculator c new CalculatorImpl()
  • Naming.rebind("rmi//localhost1099/Calcula
    torService", c)
  • catch (Exception e)
  • System.out.println("Trouble " e)
  • public static void main(String args)
  • new CalculatorServer()

26
Calculator client class
  • import java.rmi.NotBoundException
  • public class CalculatorClient
  • public static void main(String args)
  • try
  • Calculator c (Calculator)
  • Naming.lookup("rmi//lo
    calhost/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)

27
Running the calculator project
  • 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
  • gtjava CalculatorServer
  • It will start, load the implementation into
    memory and wait for a client connection.
  • In the last console, start the client program.
  • gtjava CalculatorClient
  • If all goes well you will see the following
    output
  • 1 9 18 3
  • That's it you have created a working RMI system.
    Even though you ran the three consoles on the
    same computer, RMI uses your network stack and
    TCP/IP to communicate between the three separate
    JVMs. This is a full-fledged RMI system.

28
Screenshot of calculator
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjava
    CalculatorClient
  • 1
  • 9
  • 18
  • 3
  • C\PROGRA1\JAVA\JDK151.0_0\BINgt

29
A note
  • This simple example is redone at the end using
    the simplifiedservlethandler and
    loggingservletforwarder implementing rmi through
    http tunneling

30
Computing somethinglike pi
  • http//java.sun.com/docs/books/tutorial/rmi/design
    ing.html

31
Compiling compute.java and task.java and creating
a jar file in compute directory
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjavac
    compute\compute.java
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjavac
    compute\task.java
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjar cvf
    compute.jar compute\.class
  • added manifest
  • adding compute/Compute.class(in 238) (out
    169)(deflated 28)
  • adding compute/Task.class(in 166) (out
    139)(deflated 16)

32
Jar files
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\PUBLIC1\CLASSESgt
    jar xvf compute.jar
  • created META-INF/
  • inflated META-INF/MANIFEST.MF
  • inflated compute/Compute.class
  • inflated compute/Task.class
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\PUBLIC1\CLASSESgt

33
Compile client files
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\PUBLIC1\CLASSESgt
    javac c\progra1\java\jdk151
  • .0_0\bin\client\ComputePi.java
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\PUBLIC1\CLASSESgt
    javac c\progra1\java\jdk151.0_0\bin\client\Comp
    utePi.java
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\PUBLIC1\CLASSESgt
    javac c\progra1\java\jdk151.0_0\bin\client\Pi.j
    ava

34
Start rmi registery
  • C\PROGRA1\JAVA\JDK151.0_0gtstart rmiregistry

35
The Compute example
  • At the heart of the compute engine is a protocol
    that allows jobs to be submitted to the compute
    engine, the compute engine to run those jobs, and
    the results of the job to be returned to the
    client. This protocol is expressed in interfaces
    supported by the compute engine and by the
    objects that are submitted to the compute engine,
    as shown in the following figure.
  • Each of the interfaces contains a single method.

36
About the example
  • The return value for the Compute's executeTask
    and Task's execute methods is declared to be of
    type Object. This means that any task that wants
    to return a value of one of the primitive types,
    such as an int or a float, needs to create an
    instance of the equivalent wrapper class for that
    type, such as an Integer or a Float, and return
    that object instead.

37
About the example
  • Note that the Task interface extends the
    java.io.Serializable interface. RMI uses the
    object serialization mechanism to transport
    objects by value between Java virtual machines.
    Implementing Serializable marks the class as
    being capable of conversion into a
    self-describing byte stream that can be used to
    reconstruct an exact copy of the serialized
    object when the object is read back from the
    stream.

38
About the example
  • Different kinds of tasks can be run by a Compute
    object as long as they are implementations of the
    Task type. The classes that implement this
    interface can contain any data needed for the
    computation of the task and any other methods
    needed for the computation.

39
About the example
  • Here is how RMI makes this simple compute engine
    possible.
  • Since RMI can assume that the Task objects are
    written in the Java programming language,
    implementations of the Task object that were
    previously unknown to the compute engine are
    downloaded by RMI into the compute engine's
    virtual machine as needed.
  • This allows clients of the compute engine to
    define new kinds of tasks to be run on the server
    machine without needing the code to be explicitly
    installed on that machine. In addition, because
    the executeTask method returns a
    java.lang.Object, any type of object can be
    passed as a return value in the remote call.

40
About the example
  • The compute engine, implemented by the
    ComputeEngine class, implements the Compute
    interface, allowing different tasks to be
    submitted to it by calls to its executeTask
    method. These tasks are run using the task's
    implementation of the execute method. The compute
    engine reports results to the caller through its
    return value an Object.

41
compute.Compute
  • The compute.Compute interface defines the
    remotely accessible part--the compute engine
    itself. Here is the remote interface with its
    single method
  • package compute
  • import java.rmi.Remote
  • import java.rmi.RemoteException
  • public interface Compute extends Remote
  • Object executeTask(Task t) throws
    RemoteException
  • By extending the interface java.rmi.Remote, this
    interface marks itself as one whose methods can
    be called from any virtual machine. Any object
    that implements this interface becomes a remote
    object.

42
compute.Task
  • The compute.Task interface defines the interface
    between the compute engine and the work that it
    needs to do, providing the way to start the work.
  • package compute
  • import java.io.Serializable
  • public interface Task extends Serializable
  • Object execute()
  • The Task interface defines a single method,
    execute, which returns an Object, has no
    parameters, and throws no exceptions. Since the
    interface does not extend Remote, the method in
    this interface doesn't need to list

43
the implementation class of a remote interface
  • general the implementation class of a remote
    interface should at least
  • Declare the remote interfaces being implemented
  • Define the constructor for the remote object
  • Provide an implementation for each remote method
    in the remote interfaces
  • The server needs to create and to install the
    remote objects. This setup procedure can be
    encapsulated in a main method in the remote
    object implementation class itself, or it can be
    included in another class entirely. The setup
    procedure should
  • Create and install a security manager
  • Create one or more instances of a remote object
  • Register at least one of the remote objects with
    the RMI remote object registry (or another naming
    service such as one that uses JNDI), for
    bootstrapping purposes

44
The complete implementation of the compute engine
  • The complete implementation of the compute engine
    follows. The engine.ComputeEngine class
    implements the remote interface Compute and also
    includes the main method for setting up the
    compute engine.

45
ComputeEngine
  • package engine
  • import java.rmi.
  • import java.rmi.server.
  • import compute.
  • public class ComputeEngine extends
    UnicastRemoteObject implements Compute
  • public ComputeEngine() throws RemoteException
    super() public Object executeTask(Task t)
    return t.execute()
  • public static void main(String args)
  • if (System.getSecurityManager() null)
    System.setSecurityManager(new RMISecurityManager()
    )
  • String name "//host/Compute"//change to
    localhost
  • try Compute engine new ComputeEngine()
    Naming.rebind(name, engine) System.out.println("C
    omputeEngine bound")
  • catch (Exception e) System.err.println("ComputeE
    ngine exception " e.getMessage())
    e.printStackTrace()

46
Client files class Pi implements Task, slide1
  • package client
  • import compute.
  • import java.math.
  • public class Pi implements Task
  • / constants used in pi computation /
  • private static final BigDecimal ZERO
  • BigDecimal.valueOf(0)
  • private static final BigDecimal ONE
  • BigDecimal.valueOf(1)
  • private static final BigDecimal FOUR
  • BigDecimal.valueOf(4)
  • / rounding mode to use during pi
    computation /
  • private static final int roundingMode
  • BigDecimal.ROUND_HALF_EVEN
  • / digits of precision after the decimal
    point /
  • private int digits
  • /Construct a task to calculate pi to the
    specified precision. /
  • public Pi(int digits)
  • this.digits digits

47
Client files class Pi implements Task, slide2
  • / Calculate pi. /
  • public Object execute()
  • return computePi(digits)
  • /
  • Compute the value of pi to the specified
    number of
  • digits after the decimal point. The value
    is
  • computed using Machin's formula
  • pi/4 4arctan(1/5) -
    arctan(1/239)
  • and a power series expansion of arctan(x)
    to
  • sufficient precision.
  • /
  • public static BigDecimal computePi(int
    digits)
  • int scale digits 5
  • BigDecimal arctan1_5 arctan(5, scale)
  • BigDecimal arctan1_239 arctan(239,
    scale)
  • BigDecimal pi arctan1_5.multiply(FOUR).s
    ubtract(

  • arctan1_239).multiply(FOUR)

48
Client files class Pi implements Task, slide3
  • public static BigDecimal arctan(int inverseX,
  • int scale)
  • BigDecimal result, numer, term
  • BigDecimal invX BigDecimal.valueOf(inver
    seX)
  • BigDecimal invX2
  • BigDecimal.valueOf(inverseX
    inverseX)
  • numer ONE.divide(invX, scale,
    roundingMode)
  • result numer
  • int i 1
  • do
  • numer
  • numer.divide(invX2, scale,
    roundingMode)
  • int denom 2 i 1
  • term numer.divide(BigDecimal.valueO
    f(denom), scale, roundingMode)
  • if ((i 2) ! 0) result
    result.subtract(term)
  • else result result.add(term)
  • i
  • while (term.compareTo(ZERO) ! 0)
  • return result

49
Compute client files in client directory
ComputePi
  • package client
  • import java.rmi.
  • import java.math.
  • import compute.
  • public class ComputePi
  • public static void main(String args)
  • if (System.getSecurityManager() null)
  • System.setSecurityManager(new
    RMISecurityManager())
  • try
  • String name "//" args0
    "/Compute"
  • Compute comp (Compute)
    Naming.lookup(name)
  • Pi task new Pi(Integer.parseInt(args
    1))
  • BigDecimal pi (BigDecimal)
    (comp.executeTask(task))
  • System.out.println(pi)
  • catch (Exception e)
  • System.err.println("ComputePi
    exception " e.getMessage())
  • e.printStackTrace()

50
Rmiregistry (run) and run engine (server) I
used a batch file
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtrmiregistry
  • c\PROGRA1\Java\JDK151.0_0\bingtjava
    -Djava.security.policyjava.policy engin
  • e.ComputeEngine
  • ComputeEngine bound

51
Run client- you may want a batch file
  • Client expects server name to be passed as well
    as how many digits of pi are required. Output
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtrunclient
  • c\PROGRA1\Java\JDK151.0_0\bingtjava
    -Djava.security.policyjava.policy
  • client.ComputePi localhost 20
  • 3.14159265358979323846

52
More remarks
  • Youll need to change minor code in the engine
    and client where it specifies the host url. I
    used localhost.

53
UnicastRemoteObject
  • A remote object implementation does not have to
    extend UnicastRemoteObject, but any
    implementation that does not must supply
    appropriate implementations of the
    java.lang.Object methods. Furthermore, a remote
    object implementation must make an explicit call
    to one of UnicastRemoteObject's exportObject
    methods to make the RMI runtime aware of the
    remote object so that the object can accept
    incoming calls. By extending UnicastRemoteObject,
    the ComputeEngine class can be used to create a
    simple remote object that supports unicast
    (point-to-point) remote communication and that
    uses RMI's default sockets-based transport for
    communication.

54
  • If you choose to extend a remote object from any
    class other than Unicast-RemoteObject or,
    alternatively, extend from the new JDK 1.2 class
    java.rmi.activation.Activatable (used to
    construct remote objects that can execute on
    demand), you need to export the remote object by
    calling either the UnicastRemoteObject.exportObjec
    t or Activatable.exportObject method explicitly
    from your class's constructor (or another
    initialization method, as appropriate).

55
Define the Constructor
  • The ComputeEngine class has a single constructor
    that takes no arguments.
  • The code for the constructor is
  • public ComputeEngine() throws RemoteException
    super()
  • This constructor simply calls the superclass
    constructor, which is the no-argument constructor
    of the UnicastRemoteObject class. Although the
    superclass constructor gets called even if
    omitted from the ComputeEngine constructor, we
    include it for clarity. During construction, a
    UnicastRemoteObject is exported, meaning that it
    is available to accept incoming requests by
    listening for incoming calls from clients on an
    anonymous port.

56
Passing Objects in RMI
  • Arguments to or return values from remote methods
    can be of almost any type, including local
    objects, remote objects, and primitive types.
    More precisely, any entity of any type can be
    passed to or from a remote method as long as the
    entity is an instance of a type that is a
    primitive data type, a remote object, or a
    serializable object, which means that it
    implements the interface java.io.Serializable.
  • A few object types do not meet any of these
    criteria and thus cannot be passed to or returned
    from a remote method. Most of these objects, such
    as a file descriptor, encapsulate information
    that makes sense only within a single address
    space. Many of the core classes, including those
    in the packages java.lang and java.util,
    implement the Serializable interface.

57
The rules governing how arguments and return
values are passed
  • Remote objects are essentially passed by
    reference. A remote object reference is a stub,
    which is a client-side proxy that implements the
    complete set of remote interfaces that the remote
    object implements.
  • Local objects are passed by copy, using object
    serialization. By default all fields are copied,
    except those that are marked static or transient.
    Default serialization behavior can be overridden
    on a class-by-class basis.
  • Passing an object by reference (as is done with
    remote objects) means that any changes made to
    the state of the object by remote method calls
    are reflected in the original remote object. When
    passing a remote object, only those interfaces
    that are remote interfaces are available to the
    receiver any methods defined in the
    implementation class or defined in nonremote
    interfaces implemented by the class are not
    available to that receiver.

58
Implement the Server's main Method
  • The most involved method of the ComputeEngine
    implementation is the main method. The main
    method is used to start the ComputeEngine and
    therefore needs to do the necessary
    initialization and housekeeping to prepare the
    server for accepting calls from clients. This
    method is not a remote method, which means that
    it cannot be called from a different virtual
    machine. Since the main method is declared
    static, the method is not associated with an
    object at all but rather with the class
    ComputeEngine.

59
Create and Install a Security Manager
  • The first thing that the main method does is to
    create and to install a security manager, which
    protects access to system resources from
    untrusted downloaded code running within the
    virtual machine. The security manager determines
    whether downloaded code has access to the local
    file system or can perform any other privileged
    operations. All programs using RMI must install a
    security manager, or RMI will not download
    classes (other than from the local class path)
    for objects received as parameters, return
    values, or exceptions in remote method calls.
    This restriction ensures that the operations
    performed by downloaded code go through a set of
    security checks.
  • The ComputeEngine uses a security manager
    supplied as part of the RMI system, the
    RMISecurityManager. This security manager
    enforces a similar security policy as the typical
    security manager for applets that is to say, it
    is very conservative as to what access it allows.
    An RMI application could define and use another
    SecurityManager class that gave more liberal
    access to system resources or, in JDK 1.2, use a
    policy file that grants more permissions.

60
SecurityManager
  • Here's the code that creates and installs the
    security manager
  • if (System.getSecurityManager() null)
    System.setSecurityManager(new RMISecurityManager()
    )

61
Build a JAR File of Interface Classes
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtCompute
  • c\PROGRA1\Java\JDK151.0_0\bingtjavac
    compute\Compute.java
  • c\PROGRA1\Java\JDK151.0_0\bingtjavac
    compute\Task.java
  • c\PROGRA1\Java\JDK151.0_0\bingtjar cvf
    compute.jar compute\.class
  • added manifest
  • adding compute/Compute.class(in 238) (out
    169)(deflated 28)
  • adding compute/Task.class(in 166) (out
    138)(deflated 16)

62
Server batch file
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtserver
  • c\PROGRA1\Java\JDK151.0_0\bingtjavac
    engine\ComputeEngine.java
  • c\PROGRA1\Java\JDK151.0_0\bingtrmic -d .
    engine.ComputeEngine

63
About the batch file
  • The -d option tells the rmic compiler to place
    the generated class files, ComputeEngine_Stub.clas
    s and ComputeEngine_Skel.class, in the directory
    c\home\ann\src\engine. You also need to make the
    stubs and the skeletons network accessible, so
    you must copy the stub and the skeleton class to
    the area public_html\classes.
  • Since the ComputeEngine's stub implements the
    Compute interface, which refers to the Task
    interface, you need to make these two interface
    class files network accessible along with the
    stub. So the final step is to unpack the
    compute.jar file in the directory
    c\home\ann\public_html\classes to make the
    Compute and the Task interfaces available for
    downloading.

64
unpack the compute.jar file in the directory
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjar xvf
    compute.jar
  • created META-INF/
  • inflated META-INF/MANIFEST.MF
  • inflated compute/Compute.class
  • inflated compute/Task.class

65
Create client classes
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtclient.bat
  • c\PROGRA1\Java\JDK151.0_0\bingtjavac
    client\ComputePi.java
  • c\PROGRA1\Java\JDK151.0_0\bingtjavac
    client\Pi.java

66
distribute the compute.jar file to developers of
server and client applications so that they can
make use of the interfaces.
  • When you build either server- or client-side
    classes with the javac and rmic compilers, you
    generally need to specify where the resulting
    class files should reside so that they are
    network accessible. In this example this location
    is, for UNIX, /home/user/public_html/classes,
    because some web servers allow accessing a user's
    public_html directory via an HTTP URL constructed
    as http//host/user/. If your web server does
    not support this convention, you could use a file
    URL instead. The file URLs take the form
    file/home/user/public_html/classes/ on UNIX or,
    on the Microsoft Windows platform,
    file/c/home/user/public_html/classes/. You may
    also select another type of URL, as appropriate.
  • The network accessibility of the class files
    allows the RMI runtime to download code when
    needed. Rather than defining its own protocol for
    code downloading, RMI uses URL protocols
    supported by the Java platform (for example,
    HTTP) to download code. Note that a full,
    heavyweight web server is not needed to
    accomplish this downloading of class files. In
    fact, a simple HTTP server that provides all of
    the functionality needed to make classes
    available for downloading in RMI via HTTP can be
    found at ftp//ftp.javasoft.com/pub/jdk1.1/rmi/cla
    ss-server.zip.

67
Build the Server Classes
  • The engine package contains only one server-side
    implementation class, ComputeEngine, the remote
    object implementation of the Compute interface.
    Since ComputeEngine is an implementation of a
    remote interface, you need to generate a stub for
    the remote object so that clients can contact the
    remote object. Let's say that ann, the developer
    of the ComputeEngine class, has placed
    ComputeEngine.java in the c\home\ann\src\engine
    directory and is deploying the class files for
    clients to use in a subdirectory of her
    public_html directory, c\home\ann\public_html\cla
    sses (on UNIX that would be /home/ann/public_html/
    classes, accessible via some web servers as
    http//host/ann/classes/).
  • Now let's assume that the compute.jar file is
    located in the directory c\home\ann\public_html\c
    lasses. To compile the ComputeEngine class, your
    class path must include the compute.jar file and
    the source directory itself.

68
RMI with a form for client which calls a client
servlet to access a remote method
69
Html to access servlet
  • ltHTMLgt
  • ltBODYgt
  • ltH1gtRMI AND SERVLETSlt/H1gt
  • ltFORM METHOD"get"
  • action "http//localhost8080/rmi/ClientServlet"gt
  • ltINPUT TYPE"Text" name"username"gt
  • ltINPUT TYPE"submit" value"Click me"gt
  • lt/FORMgt
  • lt/BODYgt lt/HTMLgt

70
Client servlet accesses remote method
71
The files ClientServlet
  • import javax.servlet.
  • import javax.servlet.http.
  • import java.io. import java.rmi.
  • //client implementation
  • public class ClientServlet extends HttpServlet
  • //reference to the remote server
  • private ServerHandlerInterface obj
  • //Initialize the servlet and log the
    initialization.
  • public void init(ServletConfig c) throws
    ServletException super.init(c)
  • try
  • //get a remote reference
  • obj (ServerHandlerInterface)Naming.lookup("Serve
    r")
  • catch(Exception ex)
  • System.out.println("Error "
    ex.getMessage())
  • //Perform the HTTP GET operation
  • public void doGet(HttpServletRequest
    req,HttpServletResponse res) throws
    ServletException,IOException
  • //get the name of the user
  • String name req.getParameter("username")
  • String result null

72
ServerHandlerImpl (need to do both javac and rmic)
  • import java.rmi.
  • import java.rmi.server.
  • import java.rmi.registry.
  • // server class
  • public class ServerHandlerImpl extends
    UnicastRemoteObject implements
    ServerHandlerInterface
  • //constructor
  • public ServerHandlerImpl() throws
    RemoteException System.out.println("Creating
    server object")
  • //remote method called by the servlet
  • public String servletTest(String name) throws
    RemoteException
  • String res "Your name is "name"\n" "\n\n
    Returned by RMI Server" return res
  • //main method creates an instance of the remote
    object
  • //and binds it with the registry service
  • public static void main(String args)
  • try
  • ServerHandlerImpl obj new ServerHandlerImpl()
  • Registry reg LocateRegistry.createRegistry(1099)
  • reg.rebind("Server",obj) catch(Exception ex)
  • System.out.println(ex.getMessage()) //catch

73
Remote method interface file
  • import java.rmi.
  • public interface ServerHandlerInterface extends
    Remote
  • public String servletTest(String name) throws
    RemoteException

74
You need to run this application note path
  • C\PROGRA1\TOMCAT1.5\WEBAPPS\RMI\WEB-INF\CLASSES
    gtjava ServerHandlerImpl
  • Creating server object

75
remarks
  • Need to add the servlet and mapping to web.xml
  • Need to put stub and class files for the three
    java classes into your web app.
  • Need to run the application over in the webapp
    directory--- seems like a tedious superfluity so
    wed like an example without this.

76
Generalizing the example to route requests
choose one method
77
Or another
78
The classes Router servlet
  • import javax.servlet.
  • import javax.servlet.http.
  • import java.io. import java.rmi.
  • //client implementation
  • public class RouterServlet extends HttpServlet
  • //reference to the remote server
  • private GeneralizedServerInterface obj1,obj2
  • //Initialize the servlet and log the
    initialization.
  • public void init(ServletConfig c) throws
    ServletException super.init(c)
  • try
  • //get a remote reference
  • obj1 (GeneralizedServerInterface)Naming.lookup("
    Name")
  • obj2 (GeneralizedServerInterface)Naming.lookup("
    Number")
  • catch(Exception ex)
  • System.out.println("Error "
    ex.getMessage())
  • //Perform the HTTP GET operation
  • public void doGet(HttpServletRequest
    req,HttpServletResponse res) throws
    ServletException,IOException
  • //get the name of the user
  • String name req.getParameter("methodname")

79
Implementation (needs class file but also stub
file from rmic in classes directory)
  • import java.rmi.
  • import java.rmi.server.
  • import java.rmi.registry.
  • // a server class...provides various methods
  • public class GeneralizedServerImpl extends
    UnicastRemoteObject implements
    GeneralizedServerInterface
  • //constructor
  • public GeneralizedServerImpl() throws
    RemoteException System.out.println("Creating
    server object")
  • //remote method called by the servlet
  • public String servletTest(String name) throws
    RemoteException
  • String res "Your name is "name"\n" "\n\n
    Returned by RMI Server" return res
  • //main method creates an instance of the remote
    object
  • //and binds it with the registry service
  • public int valueTest(int num) throws
    RemoteException
  • int resnum10return res
  • public static void main(String args)
  • try
  • GeneralizedServerImpl obj1 new
    GeneralizedServerImpl()
  • GeneralizedServerImpl obj2 new
    GeneralizedServerImpl()
  • Registry reg LocateRegistry.createRegistry(1099)

80
A list of services might appear in the remote
interface file
  • import java.rmi.
  • //maybe a whole list of services?
  • public interface GeneralizedServerInterface
    extends Remote
  • public String servletTest(String name) throws
    RemoteException
  • public int valueTest(int num) throws
    RemoteException

81
remarks
  • The GeneralizedServerImpl file is compiled using
    javac, then the class file is complied using
    rmic. Both output files (class and stub.class) go
    in classes directory of webapps
  • Using this rmi model we need to run the
    application impl which logs the methods into a
    registry
  • C\PROGRA1\TOMCAT1.5\WEBAPPS\RMI\WEB-INF\CLASSES
    gtjava GeneralizedServerImpl
  • Creating server object
  • Creating server object

82
A process can use registry.list() to see bound
remote interfaces
83
RemoteHttpServlet binds servlet to registry
  • try
  • registry.rebind(getRegistryName(),this)
  • catch()

84
Some links for tutorials and examples
  • http//java.sun.com/developer/JDCTechTips/2001/tt0
    227.html
  • http//java.sun.com/developer/onlineTraining/rmi/R
    MI.html
  • http//www.javacommerce.com/displaypage.jsp?names
    ecurity.sqlid18224

85
Tunneling
  • Tunneling can be used to access RMI through a
    firewall. The client connects (requests a
    service) via http to a remote server and a
    servlet routes the client to the running rmi
    server.
  • The servlet must have mapping to
  • /cgi-bin/java-rmi.cgi

86
SUN java web server
87
Requires creating war file
  • http//www.hccfl.edu/pollock/AJava/WAR/myServletWA
    R.htm
  • C\PROGRA1\JAVA\JDK151.0_0\BIN\TMP\SESSIONgtC\PR
    OGRA1\JAVA\JDK151.0_0\BIN\jar -cvf session.war
    .
  • added manifest
  • adding WEB_INF/(in 0) (out 0)(stored 0)
  • adding WEB_INF/classes/(in 0) (out 0)(stored
    0)
  • adding WEB_INF/classes/SessionInfo.class(in
    1926) (out 1051)(deflated 45)
  • adding WEB_INF/classes/SessionSnoop.class(in
    3446) (out 1755)(deflated 49)
  • adding WEB_INF/web.xml(in 1002) (out
    332)(deflated 66)

88
Deploy a webapp (war)
89
Editing webapps in sun web server
90
Configuring tomcat to listen at port 80
  • You can configure tomcat to listen at port 80
    instead of port 8080
  • The file tomacat\conf\server.xml controls the
    port where tomcat listensline 77 in my tomcat
    5.5 container
  • lt!-- Define a non-SSL HTTP/1.1 Connector on port
    8080 modified to read port 80 11/28/06--gt
  • ltConnector port"80" maxHttpHeaderSize"8192"

91
Tunneling
  • Tunneling is not a trick but is specifically
    provided for by RMI which automatically tries
    this avenue if other efforts to locate the method
    fail.
  • To force tunneling for development purposes
    when there is no firewall you add a couple of
    lines to your client
  • try
  • RMISocketFactory.setSocketFactory(new
    sun.rmi.transport.proxy.RMIHttpToCGISocketFactory(
    ))
  • Catch(IOException x)

92
Converting ANY rmi client/server into a tunneler
  • No change needed to the server.
  • Youll need to put the Impl and Impl_Stub class
    files in the classes directory of ROOT/WEB-INF
  • Remember, the stub file is created by using the
    rmi compiler on the impl class file.
  • Youll need to get the tunneler servlet files off
    the network, or from me, and deploy into
    Tomcat/webapps/Root with mapping as above
    (/cgi-bin/)

93
Example Hello client and servermodified client
  • import java.rmi.
  • import java.rmi.server.//////note additional
    imports
  • import java.io.
  • import java.rmi.registry.LocateRegistry
  • import java.rmi.registry.Registry
  • public class HelloClient2
  • private HelloClient2()
  • public static void main(String args)
  • String host (args.length lt 1) ? null
    args0
  • try /////note this addition
  • RMISocketFactory.setSocketFactory(new
    sun.rmi.transport.proxy.RMIHttpToCGISocketFactory(
    ))
  • Registry registry LocateRegistry.getRegistr
    y(host)
  • Hello stub (Hello) registry.lookup("HelloSe
    rver")
  • String response stub.sayHello()
  • System.out.println("response " response)
  • catch (Exception e)
  • System.err.println("Client exception "
    e.toString())
  • e.printStackTrace()

94
Get the server running
  • You might want to use a policy file and a batch
    file
  • Heres a java.policy file
  • grant
  • permission java.security.AllPermission
  • permission java.net.SocketPermission
    "localhost1024-", "connect,listen,accept,resolve"

95
Get the server running
  • Put the impl and impl stub files in
    ROOT/WEB-INF/classes
  • Make sure youve got that tunneler servlet
    working
  • Startup tomcat
  • Startup rmi registry
  • Run the server

96
Batch file for server run client
  • java -Djava.security.manager -Djava.security.polic
    y"java.policy" HelloImpl
  • Note--- in my version I bind HelloServer to the
    registry, not Hello so I modified the client to
    look for this
  • Output
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjava
    HelloClient2
  • response Hello World!

97
A second tunneling example
  • The calculator example from above can be easily
    modified to go through http

98
Calculator modified to go through rmi tunneling
output
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtjava
    CalculatorClient2
  • 1
  • 9
  • 18
  • 3

99
CalcClient2 forced to go through http tunnel
  • import java.net.MalformedURLException
  • import java.rmi.
  • import java.rmi.server.
  • import java.io.
  • public class CalculatorClient2
  • public static void main(String args)
  • try RMISocketFactory.setSocketFactory(ne
    w sun.rmi.transport.proxy.RMIHttpToCGISocketFactor
    y())
  • Calculator c (Calculator)
    Naming.lookup("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)

100
And more catches
  • catch (RemoteException re)
  • System.out.println()
  • System.out.println("RemoteException")
  • System.out.println(re)
  • catch (IOException io)
  • System.out.println()
  • System.out.println(
    "IOException")
  • System.out.println(io.toString())
  • 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.Arithmet
    icException")
  • System.out.println(ae)

101
No changes to calculator server
  • Need to move copy of impl and stub files to your
    server classes directory.

102
I added print statements to my cgi servlet
forwarder
103
Third example from Grossos RMI text, chapter
22.It is much more involved than the previous two
  • You can get the code off the internet look for
    Grosso RMI text

104
rmic_bankserver.bat and bankserver.bat
  • May need to edit the batch files to get rmic and
    start registry to work.
  • I removed these lines from the batch files and
    performed them in a different directory.

105
Starting registry and creating stub files via rmic
  • c\PROGRA1\Java\JDK151.0_0\bingtrmic
    com.ora.rmibook.chapter22.Account_Impl
  • C\PROGRA1\JAVA\JDK151.0_0\BINgtstart
    rmiregistry
  • C\PROGRA1\JAVA\JDK151.0_0\BINgt

106
Running the bankserver
  • c\PROGRA1\java\JDK151.0_0\bin\com\ora\rmibook\C
    HAPTE1gtjava -Djava.security.m
  • anager -Djava.security.policy"java.policy"
    com.ora.rmibook.chapter22.applicatio
  • ns.ImplLauncher Bob 10000 Alex 1223
  • Account Bob successfully launched.
  • Account Alex successfully launched.

107
java.policy file
  • grant
  • permission java.security.AllPermission
  • permission java.net.SocketPermission
    "localhost1024-", "connect,listen,accept,resolve"

108
Tunneling problems
  • The rmi client goes makes a request for a servlet
    on port 80 (not port 8080)
  • Youll need to modify the server.xml in conf
    directory of tomcat, or use another container.
  • I installed the sun webserver on my machine. It
    listens on port 80 and servlet deployment is
    fairly simple. (Though I never got it working)

109
Tunneler Running
110
I had to make some changes
  • It doesnt completely work
  • There is some error - possibly in the text code
    (to write objects)

111
The servlet and exception and other java files
are in higgindm/internet prgramming/java/tunneler
112
modifications
  • I removed the package code though it probably
    wasnt necessary
Write a Comment
User Comments (0)
About PowerShow.com