RMI - PowerPoint PPT Presentation

About This Presentation
Title:

RMI

Description:

RMI From O Reilly RMI text and internet tutorials Other rmi tutorials http://java.sun.com/developer/onlineTraining/rmi/RMI.html And http://java.sun.com/docs/books ... – PowerPoint PPT presentation

Number of Views:21
Avg rating:3.0/5.0
Slides: 128
Provided by: higg2
Category:
Tags: rmi

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
Java Remote Object Invocation (RMI)
  • Overview of RMI
  • Java RMI allows programmer to execute remote
    function class using the same semantics as local
    functions calls.

5
The General RMI Architecture
  • The server must first bind its name to the
    registry
  • The client looks up the server name in the
    registry to establish remote references.
  • The Stub serializes the parameters to the
    skeleton, the skeleton invokes the remote method
    and seriales the result back to the stub.

6
The Stub and Skeleton
  • A client invokes a remote method, the call is
    first forwarded to stub.
  • The stub is responsible for sending the remote
    call over to the server-side skeleton
  • The stub opening a socket to the remote server,
    marshaling the object parameters and forwarding
    the data stream to the skeleton.
  • A skeleton contains a method that receives the
    remote calls, unmarshals the parameters, and
    invokes the actual remote object implementation.

7
Steps for Developing an RMI System
  • 1. Define the remote interface
  • 2. Develop the remote object by implementing the
    remote interface.
  • 3. Develop the client program.
  • 4. Compile the Java source files.
  • 5. Generate the client stubs and server
    skeletons.
  • 6. Start the RMI registry.
  • 7. Start the remote server objects.
  • 8. Run the client

8
Step 1 Defining the Remote Interface
  • To create an RMI application, the first step is
    the defining of a remote interface between the
    client and server objects.
  • / SampleServer.java /
  • import java.rmi.
  • public interface SampleServer extends Remote
  • public int sum(int a,int b) throws
    RemoteException

9
Step 2 Develop the remote object and its
interface
  • The server is a simple unicast remote server.
  • Create server by extending java.rmi.server.Unicast
    RemoteObject.
  • The server uses the RMISecurityManager to protect
    its resources while engaging in remote
    communication.
  • / SampleServerImpl.java /
  • import java.rmi.
  • import java.rmi.server.
  • import java.rmi.registry.
  • public class SampleServerImpl extends
    UnicastRemoteObject
  • implements
    SampleServer
  • SampleServerImpl() throws RemoteException
  • super()

10
Step 2 Develop the remote object and its
interface
  • Implement the remote methods
  • / SampleServerImpl.java /
  • public int sum(int a,int b) throws
    RemoteException
  • return a b
  • The server must bind its name to the registry,
    the client will look up the server name.
  • Use java.rmi.Naming class to bind the server name
    to registry. In this example the name call
    SAMPLE-SERVER.
  • In the main method of your server object, the RMI
    security manager is created and installed.

11
Step 2 Develop the remote object and its
interface
  • / SampleServerImpl.java /
  • public static void main(String args)
  • try
  • System.setSecurityManager(new
    RMISecurityManager())
  • //set the security manager
  • //create a local instance of the object
  • SampleServerImpl Server new
    SampleServerImpl()
  • //put the local instance in the registry
  • Naming.rebind("SAMPLE-SERVER" , Server)
  • System.out.println("Server
    waiting.....")
  • catch (java.net.MalformedURLException me)
  • System.out.println("Malformed URL "
    me.toString())
  • catch (RemoteException re)

12
Step 3 Develop the client program
  • In order for the client object to invoke methods
    on the server, it must first look up the name of
    server in the registry. You use the
    java.rmi.Naming class to lookup the server name.
  • The server name is specified as URL in the from
    ( rmi//hostport/name )
  • Default RMI port is 1099.
  • The name specified in the URL must exactly match
    the name that the server has bound to the
    registry. In this example, the name is
    SAMPLE-SERVER
  • The remote method invocation is programmed using
    the remote interface name (remoteObject) as
    prefix and the remote method name (sum) as suffix.

13
Step 3 Develop the client program
  • import java.rmi.
  • import java.rmi.server.
  • public class SampleClient
  • public static void main(String args)
  • // set the security manager for the client
  • System.setSecurityManager(new
    RMISecurityManager())
  • //get the remote object from the registry
  • try
  • System.out.println("Security Manager
    loaded")
  • String url "//localhost/SAMPLE-SERVER"
  • SampleServer remoteObject
    (SampleServer)Naming.lookup(url)
  • System.out.println("Got remote
    object")
  • System.out.println(" 1 2 "
    remoteObject.sum(1,2) )
  • catch (RemoteException exc)
  • System.out.println("Error in lookup "
    exc.toString())

14
Step 4 5 Compile the Java source files
Generate the client stubs and server skeletons
  • Assume the program needs to compile and execute
    at home
  • Once the interface is completed, you need to
    generate stubs and skeleton code. The RMI system
    provides an RMI compiler (rmic) that takes your
    generated interface class and procedures stub
    code on its self.
  • promptgt set CLASSPATHhome
  • promptgt javac SampleServer.java
  • promptgt javac SampleServerImpl.java
  • promptgt rmic SampleServerImpl
  • promptgt javac SampleClient.java

15
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.

16
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.

17
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

18
Step 6 Start the RMI registry in its own command
window
  • Open an extra command window
  • The RMI applications need install in the
    Registry. And the Registry must be started
    manually by calling rmiregisty.
  • The rmiregistry uses port 1099 by default. You
    can also bind rmiregistry to a different port by
    indicating the new port number as rmiregistry
    ltnew portgt
  • On Windows, you have to type on the command line
  • gt start rmiregistry

19
Port for rmi
  • To run registry on Windows platforms
  • Promptgtstart 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
  • Promptgtstart rmiregistry 2001

20
Steps 7 8 Start the remote server objects
Run the client
  • Once the Registry is started, the server can be
    started and will be able to store itself in the
    Registry.
  • Because of the grained security model in Java
    2.0, you must set up a security policy for RMI by
    set java.security.policy to a file, for example,
    policy.all
  • promptgt java Djava.security.policypolicy.all
    SampleServerImpl
  • promptgt java Djava.security.policypolicy.all
    SampleClient

21
Java Policy File
  • In Java 2, the java application must first obtain
    information regarding its privileges. It can
    obtain the security policy through a policy file.
    If, in above example, we allow the Java code to
    have all permissions, the contents of the policy
    file policy.all would be
  • grant
  • permission java.security.AllPermission
  • Now, we given an example for assigning resource
    permissions
  • grant
  • permission java.io.filePermission /tmp/,
    read, write
  • permission java.net.SocketPermission
    somehost.somedomain.com999,connect
  • permission java.net.SocketPermission
    1024-65535,connect,request
  • permission java.net.SocketPermission
    80,connect

22
Comment for the Java Policy File
  • 1. allow the Java code to read/write any files
    only under the /tmp directory, includes any
    subdirectories
  • 2. allow all java classes to establish a network
    connection with the host somehost.somedomain.com
    on port 999
  • 3. allows classes to connection to or accept
    connections on unprivileged ports greater than
    1024 , on any host
  • 4. allows all classes to connect to the HTTP
    port 80 on any host.
  • You can obtain complete details by following
    links
  • http//java.sun.com/products//jdk/1.2/docs/guide/s
    ecurity/spec/security-spec.doc3.html

23
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

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

25
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()

26
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())

27
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!

28
Dont forget to run rmic on the interface
  • C\rmi_hello_worldgtrmic Hello
  • C\rmi_hello_worldgtjava HelloServer
  • Hello Server is ready.
  • C\rmi_hello_worldgtjava HelloClient
  • Hello, world!

29
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()

30
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"

31
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
  • (you get this message when it is bound)

32
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.

33
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 Firefox 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

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

35
Run the applet (the little hello world is the
message)
36
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

37
The calculator project implementation class
CalculatorImpl
  • public class CalculatorImpl extends
    java.rmi.server.UnicastRemoteObject
  • implements Calculator
  • // Implementations must have an
  • //explicit constructor
  • // in order to declare the
  • //RemoteException exception
  • public CalculatorImpl()
  • throws java.rmi.RemoteException
  • super()
  • public long add(long a, long b)
  • throws java.rmi.RemoteException
  • return a b
  • public long sub(long a, long b)
  • throws java.rmi.RemoteException
  • return a - b
  • public long mul(long a, long b)
  • throws java.rmi.RemoteException
  • return a b

38
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

39
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()

40
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)

41
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
  • gtrmiregistry
  • If all goes well, the registry will start running
    and you can switch to the next console.
  • In the second console. To start the server
    hosting the CalculatorService 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.

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

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

44
Computing somethinglike pi
  • http//java.sun.com/docs/books/tutorial/rmi/overvi
    ew.html

45
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)

46
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

47
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

48
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.

49
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.

50
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.

51
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.

52
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.

53
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.

54
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.

55
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

56
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

57
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.

58
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()

59
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

60
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)

61
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

62
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()

63
Rmiregistry (run) and run engine (server) I
used a batch file
  • gtrmiregistry
  • gtjava -Djava.security.policyjava.policy
    engine.ComputeEngine
  • ComputeEngine bound

64
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

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

66
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.

67
  • 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).

68
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.

69
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.

70
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.

71
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.

72
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.

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

74
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)

75
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

76
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.

77
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

78
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

79
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.

80
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.

81
RMI with a form for client which calls a client
servlet to access a remote method
82
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

83
Client servlet accesses remote method
84
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

85
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

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

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

88
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.

89
Generalizing the example to route requests
choose one method
90
Or another
91
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")

92
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)

93
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

94
remarks
  • The GeneralizedServerImpl file is compiled using
    javac, then the class file is compiled 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

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

97
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

98
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

99
SUN java web server
100
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)

101
Deploy a webapp (war)
102
Editing webapps in sun web server
103
Configuring tomcat to listen at port 80
  • You can configure tomcat to listen at port 80
    instead of port 8080
  • The file tomcat\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"

104
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)

105
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/) I think its at http//java.sun.com/
    j2se/1.3/docs/guide/rmi/archives/rmiservlethandler
    .zip
  • The unzipped contents also has a readme with some
    explanation.

106
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()

107
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"

108
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

109
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!

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

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

112
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)

113
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)

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

115
I added print statements to my cgi servlet
forwarder
116
Related (RMI) project
  • Maybe not too hard after all.
  • Make changes to the task/compute (PI) RMI example
    to effect RMI tunneling.

117
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

118
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.

119
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

120
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.

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

122
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)

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

125
The servlet and exception and other java files
are in higgindm/internet programming/java/tunneler
/.java
126
modifications
  • I removed the package code though it probably
    wasnt necessary

127
Tunneling with tomcat
  • Background Tunneling
  • Remote Method Invocation (RMI) in Java gives a
    clean way to build distributed applications in
    java. If you are on an Intranet with no
    firewalls, RMI just works. But on the Internet,
    where firewalls abound, RMI can be blocked
    because it tries to connect to server hosts using
    arbitrary port numbers. Typical firewalls on the
    server side don't allow this. To alleviate this
    problem, Sun built in to the RMI implementation a
Write a Comment
User Comments (0)
About PowerShow.com