MokaByte Numero 15 - Gennaio 1998

 di 
Ennio Grasso

 

Getting Started Using JRB

Un esempio pratico di questa tecnologia

 

 
 

 

 

Introduction

This paper shows you the steps to follow to create a distributed version of the classic Hello Worls program using Java Reflective Broker (JRB - pronounced jerby). I’ve purposely taken and modified the document form JavaSoft "Getting Started Using RMI" to highlight both the differences and similarities between the two communication systems.

The distributed Hello World example uses an applet to make a remote method call to the server from which it was downloaded to retrieve the message "Hello Worls!". When the applet runs, the message is displayed on the client.

To accomplish this, you will work through the following three lessons:

Write The HTML and Java Source Files

There are three source files for the Hello World server and applet:

  1. The Java remote object (server).
  2. The Java applet that remotely invokes the server's method.
  3. The HTML code for the web page that references the applet.
Because the Java language requires a mapping between the fully qualified package name of a class file and the directory path to that class, before you begin writing Java code you need to decide on package and directory names. (This mapping allows the Java compiler to know the directory in which to find the class files mentioned in a Java program.) For the Hello World program developed in this paper, the package name is examples.hello and the root directory is

$HOME/java/examples/hello.

For example, to create the directory for your source files on Solaris, execute this command:

mkdir $HOME/java/examples/hello

Define a Remote Interface

JRB doesn’t need a Remote interface: any Java class can be exported as a remote server. Even library classes can be exported without the need for the source code.

Write a Remote Class

To write a remote object, you simply need to:

  1. Create one or more instances of a Java class.
  2. Export your instances with the JRB runtime.
For example, here is the source for the HelloImpl.java file, which contains the code for the Hello World server. The code is followed by an explanation of each of the preceding steps.

package examples.hello;



import cselt.jrb.*;



public class HelloImpl {



        public String sayHello() {

                return  "Hello World!";

        }



        public static void main(String args[]) {

        try {

             HelloImpl obj = new HelloImpl();

             Server.setPort(9999);

             ObjectRef ref = Server.export("HelloServer", obj);



             System.out.println("HelloServer exported");



        } catch (Exception e) {

             System.out.println("HelloImpl err: " + e.getMessage());

             e.printStackTrace();

        }

        }

}

Implement a Remote Class

The remote class for the Hello World example is HelloImpl. The class contains the sayHello public method, which returns the string Hello World! to the caller.

public String sayHello() {

        return "Hello World!";

}

Arguments to, or return values from, remote methods can be of any Java type, including objects, as long as those objects implement the interface java.io.Serializable. Most of the core Java classes in java.lang and java.util implement the Serializable interface. Local objects are passed by copy, and only the non-static and non-transient fields are copied by default. Any public method of a class can be invoked both within the virtual machine running the service and remotely.

Create One or More Instances of a Remote Object

The main method of the service needs to create one or more instances of the remote object which provides the service. For example:

HelloImpl obj = new HelloImpl();

Export a Remote Object

For a caller (client, peer, or applet) to be able to invoke a method on a remote object, that caller must first obtain a reference to the remote object. Object references are created by exporting an object with the JRB runtime system through the export operation. export may take an extra string argument that specify the name of the exported object. If this argument is missing the JRB will assign a name to the object:

ObjectRef ref = Server.export(obj);

Most of the time the client will obtain a reference to a remote object as a parameter to, or a return value from, another remote method call. For bootstrapping, the client must be able to obtain the first reference to a remote object. The simplest way is for the server to listen on a well known port and export the object with a name also known by the client like the name "HelloServer" in example. The client can use a URL-based naming scheme of the form host:port/objectname to create an object reference, where objectname is a simple string name used in the export operation, such as HelloServer:

ObjectRef ref = new ObjectRef("duplex.cselt.it:9999/HelloServer");

Register a Remote Object

If starting a server on a well known port is considered restraining, the JRB system provides a Naming Server that allows you to bind a URL of the form host/objectname to the remote object, where objectname is a simple string name. Once a remote object is registered on the Naming Server, callers can look up the object by name, obtain a remote object reference, and then remotely invoke methods on the object. In the HelloImpl example the code:

Server.setPort(9999);
ObjectRef ref = Server.export("HelloServer", obj);

can be replaced by:

ObjectRef ref = Server.export(obj);
NamingRef naming = new NamingRef("myhost/NamingServer");
naming.rebind("myhost/HelloServer", ref);

Optionally, a port number can be supplied in the URL: for example myhost:1234/HelloServer. The port defaults to 6666. It is necessary to specify the port number only if you start the naming server on a port other than the default 6666.

Write an Applet that Uses the Remote Service

The applet part of the distributed Hello World example remotely invokes the HelloServer's sayHello method in order to get the string "Hello World!", which is displayed when the applet runs. Here is the code for the applet:

package examples.hello;



import java.awt.*;

import cselt.jrb.*;



public class HelloApplet extends java.applet.Applet {

        String message = "";

        public void init() {

                try {

                        ObjectRef ref = new ObjectRef(

                        getCodeBase().getHost() + ":9999/HelloServer");



                        message = (String)ref.invoke("sayHello");



                } catch (Exception e) {

                        System.out.println("HelloApplet exception: " +

                        e.getMessage());

                        e.printStackTrace();

                }

        }

        public void paint(Graphics g) {

                g.drawString(message, 25, 50);

        }

}

  1. The applet first gets a handle to the "HelloServer" constructing the URL by using the getCodeBase method in conjunction with the getHost method.
  2. The applet uses the reference to remotely invoke the sayHello method of the HelloServer remote object and stores the return value from the call (the string "Hello World!") in a variable named message.
  3. The applet invokes the paint method to draw the applet on the display, causing the string "Hello World!" to be displayed.
The constructed URL must include the host. Otherwise, the applet's lookup will default to the client, and the AppletSecurityManager will throw an exception since the applet cannot access the local system, but is instead limited to communicating only with the applet host.

Using the Naming Server

If the server has registered the object reference with the naming server, the applet must first lookup on the naming server and then call the remote object. The code fragment:

ObjectRef ref = new ObjectRef(

        getCodeBase().getHost() + ":9999/HelloServer");

would be replaced by:

NamingRef naming = new NamingRef(

        getCodeBase().getHost() + "/NamingServer");

ObjectRef ref = naming.lookup("HelloServer");

Write the Web Page that Contains the Applet

Here is the HTML code for the web page that references the Hello World applet:

<HTML>

<title>Hello World</title>

<center> <h1>Hello World</h1> </center>



The message from the HelloServer is:

<p>

<applet codebase="../.."

code="examples.hello.HelloApplet"

width=500 height=120>

</applet>

</HTML>

Note the following:

There needs to be an HTTP server running on the machine from which you want to download classes. The applet's codebase attribute indicates the URL, as shown here:

codebase="../.."

The codebase in this example specifies a directory two levels above the directory from which the web page was itself loaded. The applet's code attribute specifies the fully package-qualified name of the applet, in this example examples.hello.HelloApplet:

Compile and Deploy Class Files and HTML Files

The source code for the Hello World example is now complete and the $HOME/java/hello directory has three files:

In this section, you compile the .java source files to create .class files. You don’t need to create separate stub and skeleton classes because JRB uses Java Reflection to execute the call and dispatch the invocation to the target object. When you use the javac compiler, you can specify where the resulting class files should reside. For applets, all files should be in the applet's codebase directory. In this paper, this is $HOME/public_html/codebase.

Some Web servers allow accessing a user's public_html directory via an HTTP URL constructed as "http://host/~username/". If your Web server does not support this convention, you may use a file URL of the form "file://home/username/public_html".

Compile the Java Source Files

Make sure that the deployment directory $HOME/public_html/codebase and the development directory $HOME/java/examples/hello are each visible via the local CLASSPATH on the development machine. To compile the Java source files, run the javac command as follows:

javac -d $HOME/public_html/codebase
HelloImpl.java HelloApplet.java

This command creates the directory examples/hello (if it does not already exist) in the directory $HOME/public_html/codebase. The command then writes to that directory the files HelloImpl.class and HelloApplet.class. These are the server, and the applet respectively.

Generate Stubs and Skeletons

Normally, the JRB will be used without using stubs and skeletons. The invoke operation of the ObjectRef class follows the principle of the Java Reflection API that dynamically creates an invocation and dispatches the call to the remote object. If, for any reasons, the programmer is happier with a static invocation model, such as the one supported by Java RMI, the JRB provides a stub generator that creates specialized object references. A specialized reference class is a subclass of ObjectRef class and provides the same public method of the exported remote object. For example, the Naming Server of the JRB is made up of the class Naming. By applying the stub generator to this class a NamingRef class is created that provides the same methods of the Naming class and is used at the client side for remote invocations to the Naming object. Note, however, that skeletons are still not necessary. In the Hello World example, if we want to use a specialized reference to the HelloImpl class we should apply the stub generator to the HelloImpl.class file:

java cselt.jrb.Stub examples.hello.HelloImpl

Note that the stub generator is written in Java. You could create an alias of the kind:

alias stub ‘java cselt.jrb.Stub’

The stub generator creates a HelloImplRef class that represents the specialized reference to the HelloImpl class. Then clients can use HelloImplRef with the static invocation approach rather than the dynamic model of the invoke operation:

HelloImplRef ref = new HelloImplRef(
getCodeBase().getHost() + ":9999/HelloServer");

message = ref.sayHello();

This mode of operation is very RMI-like.

Move the HTML File to the Deployment Directory

To make the web page that references the applet visible to clients, the index.html file must be moved from the development directory to the codebase directory. For example:

mv $HOME/jdk1.1/mysrc/examples/hello/index.html $HOME/public_html/codebase/examples/hello

Set Paths for Runtime

Make sure that the $HOME/public_html/codebase directory is available via the server's local CLASSPATH when you run the HelloImpl server.

Start the Server and Applet

If you’re using the naming server you need to start it first. To start the naming server, execute the command:

java cselt.jrb.Naming &

The naming server by default runs on port 6666. To start the naming server on a different port, specify the port number in the command. For example, to start the naming on port 2001:

java cselt.jrb.Naming 2001 &

If the naming server is running on a port other than the default, you need to specify the port number in the URL when making calls to the naming server. For example, if the naming is running on port 2001 in the Hello World example, here is the call required to bind the URL of the HelloServer to the remote object reference:

NamingRef naming = new NamingRef("myhost:2001/NamingServer");

Similarly, the URL stored on the web page needs to specify the non-default port number, or else the applet's attempt to look up the server in the registry will fail:

<PARAM name="url" value="//myhost:2001/HelloServer">

The following command shows how to start the HelloImpl server:

java examples.hello.HelloImpl &

Once the server is running, the applet can be run. An applet is run by loading its web page into a browser or appletviewer, as shown here:

appletviewer http://myhost/~myusrname/codebase/examples/hello/index.html &

After running the appletviewer, you will see output similar to the following on your display:


 


MokaByte Web  1998 - www.mokabyte.it

MokaByte ricerca nuovi collaboratori. 
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it