3-tier-architecture

Simple Object Access Protocol

Not Yet Implemented

Remote Method Invocation

Remote Method Invocation or RMI is Javasoft’s native distributed object protocol. IIOP (Internet InterOrb Protocol) offers interoperation with CORBA (Common Object Request Broker Architecture).  RMI aims to make the location of objects transparent to the user. RMI objects can have the same method calls and can pass any base type as a parameter. User defined objects must inherit from java.io.Serialize in order to be passed as parameters or returned from remote objects. In addition all rmi methods throw the RemoteException in addition to any other exceptions.

However RMI objects differ in one key respect from their local counterparts, they are really only interfaces and therefore do not posses any data of their own. All data is held in the implementation on the server and can only be accessed through remote methods.

This has an effect on the design of the persistence layer. In a 2 – tier architecture the persistent object can provide the methods save, delete and retrieve and these methods can directly access the data within the persistent object.

User po = new User();
po.name = "fred"
po.save();

This is tidy. However in order to scale applications to 3 – tier and beyond the above approach is simply not possible with RMI.  One solution is to provide an interface and implementation for each and every persistent object in our system and then implement remote accessor methods for reading and writing attributes. Moving from 2 to multi tier architectures is then a question of replacing the local with the remote objects.

local code

remote code

import myobjects.*;
User po = new User(); 
po.setName("fred");
po.save();

import rmi.myobjects.*;
User po = remoteServer.getUser();
po.setName("fred");
po.save();

The above code fragment shows how similar the local and remote versions of the application are. However in order to achieve this similarity the developer has to go through a lot of hard work.

In the local version User simply extends PersistentObject in order to provided the required functionality. In the remote version the following steps are necessary.

  • Write the User interface

  • Write the User implementation, this will forward requests to a local persistent object of the correct type

  • Extends the remote server to offer the new object type

In addition setting and getting attributes is now a remote operation with corresponding performance overhead.

A better approach is to encapsulate the save, retrieve and delete functionality into a separate class. The system can provide local and remote versions of this class. The remote version is an adapter (see Adapter pattern, Gamma et al) for the local version of the class. Persistent objects are then be real objects passed and returned by the adapter.

Initialising the RMI Interface

The principal difference between the COBRA local and RMI interface is in initialisation. A client wishing to communicate with COBRA over RMI must first locate a remote server, it may also have to set a security manager if the RMI server is not the server from where the RMI classes were loaded (the origin server).

/*
 * Set a security manager so we can connect anywhere
 */

System.setSecurityManager(new mySecurityMangler());
p = new Properties();

As in the local version we load a properties file that defines certain runtime constants.

try {
    FileInputStream f = new FileInputStream(property_file);
    p.load(f);
} catch (Exception e) {
    System.exit(-1);
}

The properties file gives the name of the remote server, we look this up and get an instance of a remote PersistentSource.

String server = "rmi://" + p.getProperty("url");
// find remote object server

try {
    PersistentObjectFactory pof = (PersistentObjectFactory)
    Naming.lookup(server);
    PersistentSource pos = pof.getPersistentSource();

    Customer c = new Customer();
    c.setCustomerId(1001);
    c.setCustomerName("Interactive Industries Inc.");
    pos.save( c );
    c = (Account) pos.retrieve(this);

} catch (Exception e) {
    System.err.println("error saving customer");
}

The local examples shown will all work unchanged, however remember to import remote versions of PersistentObject and PersistentSet. Trans objects must be obtained from the object factory, apart from that their interface is unchanged.