Summary
Java augments its firm grounding in the principles of object-oriented programming with a rich array of network communication classes. This combination lends itself well to a Java implementation of distributed object computing. Currently, there are no fewer than eight major Java distributed object offerings, including JavaSoft's Remote Objects for Java (ROJ). ROJ supports invocation of methods on remote objects with no changes to the Java language and a minimum number of differences with the Java semantic model. This article shows how easy it is to create distributed applications using ROJ, and includes a live applet demonstrating the result. (1,700 words)
By Bret Sommers
In distributed object computing, an object reference is created locally and bound to a server object. The local program can then invoke methods on the local reference as if it were a regular, local object. The distributed object infrastructure (generally referred to as an object request broker, or ORB) transparently intercepts these method invocations and transmits the method request and its arguments to the server object (via a process referred to as marshalling), where the work is actually performed. The return values are then transmitted back to the local object.
Distributed object computing offers many advantages over traditional approaches to distributed computing, such as remote procedure calls (RPCs) or socket-based client/server communication. First, the programmer is shielded from the complexity of the underlying communication mechanism. The developer interacts with a remote object via familiar method invocations, just as she would if the object were local. Second, distributed objects inherit the distinction between interface and implementation imposed by object-oriented programming. By separating the two, developers can work in parallel without concerning themselves about the implementation details of another developer's objects.
The value of distributed object computing to business enterprise will be reflected in the benefits of standardization, lower maintenance costs, higher reusability, and greater platform independence. By wrapping legacy systems in a distributed object environment, IS managers can leverage existing system investments while concurrently pursuing greater productivity by developing newer, more advanced systems. Distributed objects provide the technological and ideological framework to enable businesses to re-engineer their enterprise-wide business processes and entities top-down in an intelligent and organized manner, without sacrificing existing assets.
The elegance of Java lends itself well to the distributed object paradigm. The Java model boasts all of the OO features necessary to build robust, highly maintainable object-oriented applications. With its rich and continually improving library of network classes, Java is also a network-centric language, as demonstrated by the applet concept. These features beg for an implementation of distributed Java objects. Not surprisingly, several efforts are already underway to add distributed extensions to the Java language.
Remote Objects for
Java
The most transparent form of distributed Java thus far is
exhibited by Sun's own Remote Objects for Java (ROJ).
JavaSoft Inc., Sun's newly hatched Java subsidiary,
announced a Remote Objects for Java Early Access Release
in March 1996. Although the release notes for this alpha
release warn of the possibility of interface changes
between it and the final product, the early access release
provides the developer with a valuable glimpse of Sun's
plans for distributing Java. For information about how to
obtain the early access release, consult the resources.
The ROJ release contains two separate approaches to distributing Java objects. The first is Java IDL, which maps industry-standard IDL (Interface Definition Language) to Java interface definitions and stubs. The second is Java RMI (Remote Method Invocation), which skips the IDL step and permits the developer to develop remote objects directly in the Java language using types derived from the RMI base classes.
Real world example
To illustrate how simple it is to distribute Java with RMI, we will
proceed with a real-world example, complete with a live example applet.
Consider a typical problem faced by many would-be on-line shopping
ventures -- credit card validation. Since it is physically impossible
to perform cash transactions over the Internet, most on-line shopping
services require credit cards as a form of payment. When a patron
enters his credit card information and submits a purchase request, the
credit card information must be validated before the purchase can be
confirmed and filled.
Most commerce servers validate this information off-line, informing the unfortunate shopper via email or other means if their plastic bounced. It would be desirable if the shopping service provider could contact a live credit card validation service and inform the user immediately if their purchase request has been authorized or rejected. To prototype such a service using Java RMI requires remarkably little coding effort.
Interface
The first task is to create the interface for the remote
object. We will call the credit card validating interface
PlasticValidator. It is defined by the Java
interface definition in Listing
One.
This simple interface defines two methods,
connect() and validatePlastic(),
that must be supported by its implementors. Note that
the interface must extend the
sunw.rmi.RemoteObject interface (which is
empty in alpha1). Also, each method must throw a
sunw.rmi.RemoteException. A
RemoteException indicates an error during a
remote invocation, such as an interruption of the physical
network connection.
The connect() method will take a vendor ID
and password (both simple Java Strings). This
method is used in our scenario to simulate a login to the
credit card validating service. If the client's vendor ID
and password are valid, connect() will
return a session ID that can be used in further
transactions.
The other method, validatePlastic(), takes
this session ID, a customer's credit card, and a purchase
amount and either authorizes or denies the charge. The
CreditCard class is defined in Listing
Two. Note that any class passed in an RMI method must
be final. Furthermore, the class must have no fields that
are either private, non-final, static, or native, and
must have a public constructor method with no arguments.
Sun promises that some or all of these limitations will be
lifted in future ROJ releases.
We have now defined the complete
PlasticValidator interface. This is all the
information a client needs to know about a
PlasticValidator in order to invoke remote
methods through it. This separation of interface and
implementation is one of the building blocks of
object-oriented computing.
By keeping interface separate from implementation, developers are free to develop objects independently of each other. Although the implementation may change as time goes by, as long as the interface remains constant, objects can continue interacting. This separation becomes even more important in distributed object computing, since, as in our scenario, the developers of communicating objects may not even know each other, and may even work for competing employers.
Implementation
The actual implementation of
PlasticValidator can be found in the class
PlasticValidatorImpl, whose source can be
found in Listing
Three.
The next step in implementing a distributed RMI system is
to create a client and a server. For our purposes, the
simple server in Listing
Four will suffice. The server first sets its port to
4444 using the sunw.rmi.Control services.
This is the port on which the server will listen for
incoming connections. The server then publishes an
instance of PlasticValidatorImpl using the
sunw.rmi.Naming services. Once published, an
object becomes available for remote invocation.
Listing
Five implements a
PlasticValidatorClient. In practice, the
client would probably be part of a larger program, such as
a Java applet running inside of a Web browser. Note the
reference to a remote object encoded as a URL. An RMI
client refers to the remote object via a URL composed of a
machine, port, and published object name, preceded by the
rmi:// URI tag. A call to
sunw.rmi.Naming.resolve() with this URL is
all that is needed to bind a local instance of the
interface PlasticValidator to the remote
object instantiated by the server in the code above. If
you intend to try out the examples, you will need to
replace rmi.firstwombat.com with the name of
your server.
The final step is to generate the RMI classes that will serve as the behind-the-scenes glue. RMI classes include skeletons, stubs, and marshallers. Although it is not necessary to understand how these classes work, it is interesting to look at the generated code to get an idea of how RMI accomplishes its magic. Beware, however, as the underpinnings of RMI are quite complex, mostly because they inherit the complexity of the Spring operating system research project, upon which ROJ is based. Rather than recode the wheel, Sun chose to reuse the doors concept pioneered in Spring to implement much of ROJ's underlying plumbing. For pointers to more information about Spring, consult the resources.
To generate the RMI classes, we use a utility called
rmigen, which is included with the ROJ
release. We call rmigen on each remote object
interface .java file:
% rmigen PlasticValidator.java
This command will create and compile the following
.java source files:
Rmi_CreditCardMash.java,
Rmi_PlasticValidatorSkel.java, and
Rmi_PlasticValidatorStub.java.
rmigen will also compile these
.java files automatically to their
corresponding .class files.
Testing, 1, 2, 3
We can now install and test our prototype.
On the client machine, place these files in a common directory:
CreditCard.class
PlasticValidator.class
PlasticValidatorClient.class
Rmi_CreditCardMash.class
Rmi_PlasticValidatorStub.class
On the server machine, place these files in a common directory:
CreditCard.class
PlasticValidator.class
PlasticValidatorImpl.class
PlasticValidatorServer.class
Rmi_CreditCardMash.class
Rmi_PlasticValidatorSkel.class
Rmi_PlasticValidatorStub.class
To test the prototype, first start the server. If all goes well, the server will report that it has successfully created and bound the remote object.
Next, start the client. You should see the client
reporting its progress as it obtains a remote object
reference to the object running on the server. You will
then see a sample distributed transaction take place. On
both sides of the transaction, you will see progress
messages. Here is a transcript:
<< Server >>
% java PlasticValidatorServer
Creating PlasticValidatorImpl@de3015d8
Done creating and binding PlasticValidator object.
Vendor #245A123WXJZ connecting.
Verifying vendor password.
Vendor verified.
Validating credit card #1231 1234 3452 1234
Card member: Ima Wombat
Purchase Amount: $123.45
Purchase authorized.
<< Client >>
% java PlasticValidatorClient
Connecting to First Wombat Bank.
Connected. Session ID: dummySessionID
Attempting to authorize purchase.
Authorization: 12345678
You can also try out our Remote Objects for Java demo applet that resides on a server located at JavaWorld's headquarters. Note, however, that if your computer lives behind a firewall, chances are the applet won't run properly in your browser, as RMI requires the applet to open a socket connection back to JavaWorld.
Remote possibilities
With very little coding effort, we have created a
prototype for a very valuable and marketable service that
could be deployed on the Internet today. As distributed
object computing becomes more viable and vogue as time
progresses, we should see the rise of a rich library of
distributed objects available on the Internet. Entire
class libraries could be deployed on the Internet as
distributed objects, enabling Java programmers around the
world to use them in their own applets and applications.
As the information superhighway girl once said, There is
no there, only here.
About the author
Since graduating from Berkeley last year, Bret Sommers has served as a
Senior Associate with Cambridge
Technology Partners, an international systems consulting firm
headquartered in Cambridge, MA. Bret's current Java projects include
serving as a trial co-editor of Digital
Espresso and porting the Java RMI infrastructure to PowerBuilder,
enabling this popular 4GL to communicate seamlessly with Java objects.
He can be reached at bret.sommers@javaworld.com.
zcat ROJ-alpha1.tar.Z | tar xf
-. Be sure to include the classes
directory of the ROJ release in your
CLASSPATH variable.
If you have general comments about JavaWorld, contact
editors@javaworld.com
If you have problems with this magazine, contact
webmaster@javaworld.com
URL: http://www.javaworld.com/jw-06-1996/jw-06-remote.objects.html
Last updated: 15 May 1996