33.

previous chapter table of contents next chapter
  

Jini Classes

A simple Jini service can use an RMI proxy, where the service just remains in the server and the client makes remote method calls on it. The service will hold an RCXPort and will feed the messages through it. This involves constructing the hierarchy of classes shown in Figure 17-1.

click to expand
Figure 17-1: Class diagram for MINDSTORMS with RMI proxies

The RCXPortInterface just defines the methods we will be making available from the Jini service. It doesn't have to follow the RCXPort methods completely, because these will be wrapped up in implementation classes, such as RCXPortImpl . The interface is defined as follows :

 /**  * RCXPortInterface.java  */ package rcx.jini; import net.jini.core.event.RemoteEventListener; public interface RCXPortInterface extends java.io.Serializable {     /**      * constants to distinguish message types      */     public final long ERROR_EVENT = 1;     public final long MESSAGE_EVENT = 2;     /**      * Write an array of bytes that are RCX commands      * to the remote RCX.      */     public boolean write(byte[] byteCommand) throws java.rmi.RemoteException;     /**      * Parse a string into a set of RCX command bytes      */     public byte[] parseString(String command) throws java.rmi.RemoteException;     /**      * Add a RemoteEvent listener to the RCX for messages and errors      */     public void addListener(RemoteEventListener listener)         throws java.rmi.RemoteException;     /**      * The last message from the RCX      */     public byte[] getMessage(long seqNo)         throws java.rmi.RemoteException;     /**      * The error message from the RCX      */     public String getError(long seqNo)         throws java.rmi.RemoteException; } // RCXPortInterface 

We have chosen to make a subpackage of the rcx package and to place the preceding class in this package to make its role clearer. Note that the RCXPortInterface has no static methods, but makes parseString() into an ordinary instance method.

This interface contains two types of methods: those used to prepare and send messages to the RCX (write() and parseString()) , and those used to handle messages sent from the RCX (addListener() , getMessage() , and getError()) . Any listener that is added will be informed of events generated by implementations of this interface by having the listener's notify() method called. However, a RemoteEvent does not contain detailed information about what has happened , as it only contains an event type (MESSAGE_EVENT or ERROR_EVENT) . It is up to the listener to make queries back into the object to discover what the event meant , which it does with getMessage() and getError() .

The RemoteRCXPort interface just adds the Remote interface:

 /**  * RemoteRCXPort.java  */ package rcx.jini; import java.rmi.Remote; public interface RemoteRCXPort extends RCXPortInterface, Remote { } // RemoteRCXPort 

The RCXPortImpl constructs its own RCXPort object and feeds methods, such as write() , through to it. Since it extends UnicastRemoteObject , it also adds exceptions to each method, which cannot be done to the original RCXPort class. In addition, it picks up the value of the port name from the port property. (This follows the example of the RCXLoader in the rcx package, which provides a GUI interface for driving the RCX.) It looks for this port property in the parameters.txt file, which should have lines such as this:

 port=/dev/ttySO 

Note that the parameters file exists on the server side ”no client would know this information!

The RCXPortImpl also acts as a listener for "ordinary" RCX events signaling messages from the RCX. It uses the callback methods receivedMessage() and receivedError() to create a new RemoteEvent object and send it to the implementation's listener object (if there is one) by calling its notify() method.

The implementation looks like this:

 /**  * RCXPortImpl.java  */ package rcx.jini; import java.rmi.server.UnicastRemoteObject; import net.jini.core.event.RemoteEvent; import net.jini.core.event.RemoteEventListener; import rcx.*; import java.io.*; import java.util.*; public class RCXPortImpl extends UnicastRemoteObject     implements RemoteRCXPort, RCXListener {     protected String error = null;     protected byte[] message = null;     protected RCXPort port = null;     protected RemoteEventListener listener = null;     protected long messageSeqNo, errorSeqNo;     public RCXPortImpl()         throws java.rmi.RemoteException {              Properties parameters;         String portName = null;         File f = new File("parameters.txt");         if (!f.exists()) {             f = new File(System.getProperty("user.dir")                          + System.getProperty("path.separator")                          + "parameters.txt");         }         if (f.exists()) {             try {                 FileInputStream fis = new FileInputStream(f);                 parameters = new Properties();                 parameters.load(fis);                 fis.close();                 portName = parameters.getProperty("port");             } catch (IOException e) { }         } else {             System.err.println("Can't find parameters.txt                                 with \"port=...\" specified");             System.exit(1);         }         port = new RCXPort(portName);         port.addRCXListener(this);     }     public boolean write(byte[] byteCommands)         throws java.rmi.RemoteException {         return port.write(byteCommands);     }     public byte[] parseString(String command)         throws java.rmi.RemoteException {         return RCXOpcode.parseString(command);     }     /**      * Received a message from the RCX.      * Send it to the listener      */     public void receivedMessage(byte[] message) {         this.message = message;         // Send it out to listener         if (listener == null) {             return;         }         RemoteEvent evt = new RemoteEvent(this, MESSAGE_EVENT,                                            messageSeqNo++, null);         try {             listener.notify(evt);         } catch(net.jini.core.event.UnknownEventException e) {             e.printStackTrace();         } catch(java.rmi.RemoteException e) {             e.printStackTrace();         }     }     /**      * Received an error message from the RCX.      * Send it to the listener      */     public void receivedError(String error) {         // System.err.println(error);         // Send it out to listener         if (listener == null) {             return;         }         this.error = error;         RemoteEvent evt = new RemoteEvent(this, ERROR_EVENT, errorSeqNo, null);         try {             listener.notify(evt);         } catch(net.jini.core.event.UnknownEventException e) {             e.printStackTrace();         } catch(java.rmi.RemoteException e) {             e.printStackTrace();         }     }     /**      * Expected use: the RCX has returned a message,      * and we have informed the listeners. They query      * this method to find the message for the message      * sequence number they were given in the RemoteEvent.      * We could use this as an index into a table of messages.      */     public byte[] getMessage(long msgSeqNo) {         return message;     }     /**      * Expected use: the RCX has returned an error message,      * and we have informed the listeners. They query      * this method to find the error message for the error message      * sequence number they were given in the RemoteEvent.      * We could use this as an index into a table of messages.      */     public String getError(long errSeqNo) {         return error;     }     /**      * Add a listener for RCX messages.      * Should allow more than one, or throw      * TooManyListeners if more than one registers      */     public void addListener(RemoteEventListener listener) {         this.listener = listener;         messageSeqNo = 0;         errorSeqNo = 0;     } } // RCXPortImpl 
  


A Programmer[ap]s Guide to Jini Technology
A Programmer[ap]s Guide to Jini Technology
ISBN: 1893115801
EAN: N/A
Year: 2000
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net