Introduction to Distributed Objects

(based on Doreen L. Galli, Distributed Operating Systems Concepts and Practice, Chapter 6, Object-Based Operating Systems,)

The idea of distributed objects is an extension of the concept of remote procedure calls. In a remote procedure call system (Sun RPC, DCE RPC, Java RMI), code is executed remotely via a remote procedure call. The unit of distribution is the procedure / function /method (I mean these all as synonyms). So the client has to import a client stub (either manually as in RPC or automatically as in RMI) to allow it to connect to the server offering the remote procedure.

In a system for distributed objects, the unit of distribution is the object. That is, a client imports a "something" (in Java's JINI system, it's called a proxy) which allows the client access to the remote object as if it were part of the original client program (as with RPC and RMI, sort of transparently). A client actually imports a Java class and this becomes part of the set of classes available on the client machine. So, for example, the client can define subclasses of this imported class, overload methods, etc.

In addition, distributed object systems provide additional services, like a discovery service that allows clients to locate the objects they need, security services, reliability services, etc.

The three main distributed object technologies are

1.
DCOM (Distributed Common Object Model), developed by Microsoft, but also available on other platforms.
2.
CORBA (Common Object Request Broker Architecture), defined by the Object Management Group, an industry consortium. CORBA is available for most major operating systems
3.
JINI (JINI is not initials -- a joke; JINI actually doesn't stand for anything.) JINI is developed on top of Java, and is just starting to come into use. JINI was released by Sun in January, 1999.

JINI

(based on W. Keith Edwards, Core JINI and The JINI Specification by Arnold, et al)

JINI is a distributed object technology developed by Sun, party to make better distributed programming tools available to Java programmers, and party to overcome some of the inherent problems with distributed programming.

JINI source code is available under what Sun calls the Sun Community Source Licensing. It's sort of like Open Source License, but Sun wants to be able to control the development of the code (i.e., Sun want to be in charge).

Note that there is no cost for developing applications that use JINI technology, unless you are modifying the JINI source code.

You can sign up at http://java.sun.com/products/jini/licensing/

Problems with Distributed Programming

There are a number of problems with distribute programming which don't arise in non- distributed programming.

Naturally, JINI handles the problems below the line.

Some JINI Scenarios

Here are some scenarios that the JINI developers describe as examples of how JINI might be use.

Consumer appliances: The idea here is that JINI will be embedded into consumer electronic products, so that, for example, your telephone could use Java to talk to your answering machine. Or, suppose you have a wireless network in your house. Your refrigerator could communicate automatically with your Handheld PC to tell it to add "milk" to your shopping list. And if you got a new refrigerator, the refrigerator and the Handheld PC would automatically find each other, without any user intervention. Perhaps more realistically, your answering machine could send it's messages to your PC, and this would work the same whether you were using your desktop machine, your laptop, or your Palm device. Or on your digital camera, you could select Print on the camera, and the camera would automatically find an appropriate printer to print on.

Computers: In an office environment, what happens if you have desktop PCs, and you install a new printer. What happens now -- the administrator (or each user) has to install the printer on each PC. On a Unix system, users have to know to request the new printer (lpr --Pps3). With JINI, each client machine could automatically discover when a new printer has been installed, and either automatically install it as the default printer or make it available to the user from a list of printers.

Basic JINI Concepts

Required Servers

The following servers must be run to use JINI

JINI services are organized into communities. All the machines in a community will have access to the same set of services (shared resources), and a community must have one or more Lookup Services running on it. If there's more than one Lookup Service in a community, then they make the same set of services available, and the multiple Lookup services are for redundancy in case of a failure or for improved performance.

By default, a community is all the machines on your local network. If the administrator chooses, the community may be set up to be a smaller group (for example, at WPI the communities could be organized on department level, or in a company at the level of a workgroup.) Also, distinct communities can be federated, so that (some or all of) the services in one community are made available to clients in another community. In this way, the idea of a JINI community is scalable, and the presence of a central (per community) Lookup Service is not a barrier to scalability.

The five key concepts of JINI:

1.
Discovery
2.
Lookup
3.
Leasing
4.
Remote Events
5.
Transactions

Discovery

Discovery is the process by which client find which community they belong to, and where their lookup service is located. There are several discovery protocols:

Registering a Service (Join)

The name of the service that runs the Lookup Service is called the ServiceRegistrar , hence "reggie". The discovery process returns a interface to the ServiceRegistrar, which a service uses to register. The service uses the register() method of this interface to register itself with the ServiceRegistrar. The service passes two parameters to the ServiceRegistrar: a proxy and a set of attributes.

The proxy is serializable Java object (if you don't know Java, it's just Java code that can be downloaded to another machine, like applets are). The proxy is what is downloaded to the client when the client wants to use the service. The client calls a method in the proxy, and the proxy takes care of contacting the server, or whatever it has to do to perform the service. The proxy is like the RMI stub (which is downloaded from the server to the client and runs on the client to handle the communications with the server) but it's much more general. It could just be an RMI stub, which marshals the data and communicated it to the server. Bu, for example, the proxy could contact three different machines if that's what was necessary to perform its service (for example, the proxy might have to consult databases that live on several different machines). The proxy might be something like a printer driver, so that when a new printer becomes available, clients obtain the printer driver for the new printer through the JINI Lookup process. The proxy can even do all the work within its own code without contacting any other machine, if that's what's appropriate. So the proxy is mobile code which is downloaded to the client to perform any necessary work.

Proxies really represent a paradigm shift in distributed programming. In the past, the principle of distributed computing was to move the data to the code. That is, you had code (servers) running on certain machines, and to use them, clients sent data to the server machines. Even in RPC or RMI, which involved running stub programs on the client machines, task of the code on the client machines was just to move the data to the server machines (marshalling, data conversion, network transport), so RPC / RMI still represents a move-the-data-to-the-code philosophy. With proxies, you can move arbitrary code to the clients. (Mobile code is of course one of the key ideas of Java -- applets are a prime example of mobile code.)

The attributes are values the service uses to describe itself to the ServiceRegistrar and, through the ServiceRegistrar, to potential clients. There are some standard attributes that a service must provide: service name, location (server machine and port number), comments. But it's also possible to have other attributes. A printer, for example, might have attributes that indicate that it's a printer, a laser printer, and a color printer. Then when a client is looking for a color printer, it can search for attribute values rather than a service name. According to the Core JINI book, Sun is having conversations with industry groups to come up with a standard set of attributes and values for common services.

Finding a Service (Lookup)

The ServiceRegistrar interface has a method called lookup, which allows clients to look for a service. The lookup call allows the client to specify the type of the proxy (i.e., the name of the interface the proxy implements), the unique identifier of the service, or by attribute values. As a result of the lookup call, the client gets the proxy, which it uses to perform the service.

How does the client know what methods the proxy has. The client needs to know the names of the methods ahead of time.

One possibility is that the client knows the specific interface that the server implements. For example, if a client needs to print a bitmap, it might look for a service that implements the GraphicPrinter interface. (I just made this up, but something like this could be a standard JINI interface name). The they would know that the proxy that implemented this interface would have a printBitmap method, and so the client could call that method.

Another possibility is that the proxy would have its own user interface, and so the client machine wouldn't have to know what the proxy does, other than that it displays an interface to the user. So the client could search for services that have an attribute "arcade game", download the proxy, and run it. Then it would be up to the (human) user to interact with the interface; the user's commands to the interface would be handled by the proxy, which might modify the interface on its own, and might pass on data to the server. Another possibility is controlling a remote digital camera, which the user could control from an interface on the client machine.

Leasing

Leasing refers to the fact that instead of giving clients access to resources indefinitely, servers grant permission to use their service for a fixed period of time (a lease). Leases can be renewed, but only by explicit action of the client.

One way leasing is used is by the Lookup Service. From the standpoint of the Lookup service, the servers that register with it are clients. The lease from the Lookup Service to its clients (the JINI services) are for a fixed duration, and must be renewed periodically by the servers. So if a service crashes, or if it's removed from the system without a proper shut-down (for example, someone unplugs the printer to remove it, so it can't remove itself from the Lookup Service), eventually it just disappears from the Lookup Server, and clients will not be directed towards this non-existent service indefinitely. (In the RPC portmapper for example, a registered service stay there forever unless it's explicitly removed.) So leasing is one way in which a Java community is self-repairing, increasing reliability.

Another way leasing is used is between a JINI service and its clients. The same principle applies. Since the server only grants a lease for a fixed period of time. If the server dies, the client will not be able to renew its lease after the next lease expiration, and the client will have to go back to the Lookup Server to find another server to perform this service. More self-healing, more reliability. Contrast this with what happens if a network printer dies on LAN. On the CS system, the only way you know that the printer has died is that your printing doesn't appear. (You can actually check by running lpq --Pprintername, but you have to think to do this.) The some administrator has to clear out the print queue and re-start the printer. Much easier if we used JINI to connect the client and printer.

Remote Events

The Java event model can be used to allow services to notify clients when events of interest occur. There is a Java interface RemoteEventListener that must be implemented by objects that which to receive events, and single method in this interface, notify(). RemoteEventListener itself is a Remote interface, so notify can be invoked by remote objects via RMI. This means that a server can invoke a method running on a client. (This surely is a violation of the normal sense of what clients and servers can do -- a good thing because of the power it gives you in designing distributed applications.) Of course the client has to be programmed to work correctly with the events that the server might invoke.

So what can you with remote events? Back to the example of the digital camera (the client) looking for a printer (service). Suppose when the camera is placed on the network, no appropriate printer is available on the network. (The camera queried the Lookup Service and didn't find a printer service.) The client could listen for an event, to be invoked by the Lookup Service, to inform it when a printer becomes available. So the Print button on the camera interface would be greyed-out when the camera starts up (because no printer is available) and then would automatically be enabled when a printer becomes available.

Alternatively, a printer could trigger events on their clients when some unusual event occurs, like out-of-paper, and the client could take appropriate actions (like relaying this message to the user, or making the printer unavailable until the condition is corrected.

Transactions

A problem with any kind of sequence of operations (whether distributed or not) is that there might be a problem if only some of the actions in the sequence are completed. For example, suppose you wanted to transfer $100 from your checking account to your savings account. This would be accomplished by a series of actions like this:

1. Subtract $100 from your checking account
2. Add $100 to your savings account

You would be fairly upset if step 1 got executed but the machine crashed before step 2 got executed -- you would be out $100. The general computer science soluntion to this problem is to use transactions: transactions assure that all or none of the steps within a transaction are executed. From a transactional point of view, it doesn't matter whether all or none of the steps are performed -- either one leave the system in a consistent state. (If you've taken the database course, you learned all about transactions. This isn't the place to go over how transactions are executed.)

In a distributed system, there are even more chances for things to go wrong -- you can have serveral servers involved in processing the steps, servers can go down, messages can get lost, etc. JINI provides a transaction-based interface, TransactionParticipant, which allow a client and server to implement transaction-based series of actions. The TransactionParticipant interface doesn't actually provide the transaction code, but just provides a mechanism for the programmer to implement transactions.